我一直在研究在生产代码中使用Reactive UI的可行性。一些功能真的很吸引人,但我担心依赖这个库。其中包括:
RaiseAndSetIfChanged
方法取决于以下划线开头的私有成员。我理解Paul Betts(ReactiveUI作者)有Ruby背景,所以我想这就是奇怪的命名源于此。但是,这会给我带来真正的问题,因为标准命名(根据Stylecop)在整个项目中都是强制执行的。即使没有强制执行,我也会担心这会导致命名的不一致。奇怪的设计,部分。例如,日志记录是抽象的,以便不依赖于特定的日志记录框架。很公平。但是,由于我使用log4net(而不是NLog),我需要自己的适配器。我认为这将需要我实现IRxUIFullLogger
,其中包含一个公制的方法(超过50)。我认为一个更好的方法是定义一个非常简单的接口,然后在ReactiveUI中提供扩展方法以促进所有必需的重载。另外,NLog程序集所依赖的这个奇怪的IWantsToRegisterStuff
接口,我将无法依赖它(因为它是一个内部接口)。我希望我不需要那个......
无论如何,我关注的是图书馆的整体设计。有没有人被这个咬过?
有没有人有在生产中使用Reactive UI的实践经验?如果是这样,您是否能够减轻或解决我上述任何疑虑?
答案 0 :(得分:32)
让我们一点一点地解决你的问题:
#1。 “哇哇的命名和惯例。”
现在ReactiveUI 4.1+具有CallerMemberName,您根本不必使用这些约定(即使这样,您也可以通过RxApp.GetFieldNameForPropertyFunc
覆盖它们)。只需写一个属性:
int iCanNameThisWhateverIWant;
public int SomeProperty {
get { return iCanNameThisWhateverIWant; }
set { this.RaiseAndSetIfChanged(ref iCanNameThisWhateverIWant, value); }
}
#2。缺乏文档/样本
这是合法的,但这里有更多的文档/样本:
#3。 “我认为更好的方法是定义一个非常简单的接口,然后在ReactiveUI中提供扩展方法以促进所有必需的重载”
实现IRxUILogger
,它只有两种方法:) ReactiveUI将填写其余的。 IRxUIFullLogger
仅在您需要时才会出现。
“此外,还有这个奇怪的IWantsToRegisterStuff界面”
你不需要知道这个:)这只是为了处理ReactiveUI初始化自己,所以你不必有样板代码。
- “我怀疑两者混合在一个代码库中会非常令人困惑。”
醇>
不是真的。只需将其视为“具有SuperPowers的MVVM Light”。
答案 1 :(得分:12)
我的回答是在一些生产系统中使用ReactiveUI的人,RxUI的工作方式存在问题,并提交了补丁以尝试解决我遇到过的问题。
免责声明:我没有使用RxUI的所有功能。原因是我不同意这些功能的实现方式。我会随时详细说明我的变化。
命名。我觉得这也很奇怪。这最终成为我没有真正使用的功能之一。我使用PropertyChanged.Fody使用AOP编织更改通知。因此,我的属性看起来像自动属性。
DOCO。是的,还有更多。尤其是路由等新部件。这可能是我不使用所有RxUI的原因。
记录日志。我以前遇到过这方面的问题。见pull request 69。在一天结束时,我将RxUI视为一个非常固执的框架。如果您不同意该意见,您可以建议更改,但这就是全部。意见不会让它变坏。
我在Caliburn Micro上使用RxUI。 CM处理View-ViewModel位置和绑定,屏幕和指挥。我不使用CM的约定绑定。 RxUI处理Commands和ViewModel INPC代码,并允许我使用Reactive而不是传统方法对属性更改做出反应。通过将这些东西分开,我发现将两者混合起来要容易得多。
这些问题是否与生产准备有关?不。 ReactiveUI是稳定的,具有相当大的用户群,问题可以在google group中快速解决,Paul可以接受讨论。
答案 2 :(得分:5)
我在生产中使用它,到目前为止RxUI已经非常稳定。应用程序在稳定性方面存在问题,有些与EMS有关,有些用UnhandledException处理程序导致了比解决问题更多的问题,但我对应用程序的ReactiveUI部分没有任何问题。但是,我有一些关于ObservableForProperty根本没有触发的问题,我可能使用不当,并且在我的测试代码中以及在运行时的UI中一致地(错误地)工作。
-1。 Paul解释说_Upper是由于使用反射来到你班级的私人领域。您可以使用下面的块来处理StyleCop和Resharper消息,这些消息很容易生成(来自Resharper SmartTag)
/// <summary>The xxx view model.</summary>
public class XXXViewModel : ReactiveObject
{
#pragma warning disable 0649
// ReSharper disable InconsistentNaming
[SuppressMessage("StyleCop.CSharp.NamingRules",
"SA1306:FieldNamesMustBeginWithLowerCaseLetter",
Justification = "Reviewed. ReactiveUI field.")]
private readonly bool _IsRunning;
[SuppressMessage("StyleCop.CSharp.NamingRules",
"SA1306:FieldNamesMustBeginWithLowerCaseLetter",
Justification = "Reviewed. ReactiveUI field.")]
private string _Name;
....
或从完整
更改您的媒体资源 /// <summary>Gets or sets a value indicating whether is selected.</summary>
public bool IsSelected
{
get { return _IsSelected; }
set { this.RaiseAndSetIfChanged(x => x.IsSelected, value); }
}
到其组成部分,如
/// <summary>Gets or sets a value indicating whether is selected.</summary>
public bool IsSelected
{
get { return _isSelected; }
set
{
if (_isSelected != value)
{
this.RaisePropertyChanging(x => x.IsSelected);
_isSelected = value;
this.RaisPropertyChanged(x=>x.IsSelected);
}
}
}
如果您实际上没有提供“简单”属性访问器,此模式也很有用,但可能需要更多派生变量,其中设置一个值会影响多个其他值。
-2。是的,文档并不理想,但我发现在Rx之后,拿起RxUI样本非常容易。我还注意到,从2> 4的跳转似乎都伴随着支持Windows 8 / Windows 8 Phone的变化,并且为Windows Store应用程序选择了ReactiveUI,然后DotNet 4.5支持非常出色。即使用[CallerName]现在意味着你只需要.RaiseAndSetIFChanged(value)就不需要表达式。
-3。由于我没有选择使用它,我对伐木方面没有任何反馈。
-4。我也没有和其他框架混在一起。
在http://blog.paulbetts.org/index.php/2012/12/16/reactiveui-4-2-is-released/还有一个ReactiveUI 4.2的其他贡献者列表,包括Phil Haack。