我最近编写了两个类和一个接口作为实现this question of mine答案的方法。
第一个类是Notifier泛型类:
public interface INotifier { }
public class Notifier<T> : Observable,INotifier where T:new()
{
public Notifier()
{
V = new T();
}
private T _ValueBacker;
public T V
{
get { return _ValueBacker; }
set
{
_ValueBacker = value;
OnPropertyChanged(() => V);
}
}
}
这里的Observable基类只是一个实现INotifyPropertyChanged并定义OnPropertyChanged方法的类。
感谢这个类,我现在可以像这样定义一个Silverlight / WPF ViewModel:
public class Person : ViewModelBase
{
Notifier<string> Name {get;set;}
Notifier<string> Surname {get;set;}
Notifier<int> Age {get;set;}
}
而不是:
public class Person : Observable
{
private string _Name;
public string Name
{
get
{
return _Name;
}
set
{
_Name=value;
OnPropertyChanger(()=>Name);
}
}
privaate string _Surname;
public string Surname
{
get
{
return _Surname;
}
set
{
_Surname=value;
OnPropertyChanger(()=>Surname);
}
}
private int _Age;
public int Age
{
get
{
return _Age;
}
set
{
_Age=value;
OnPropertyChanger(()=>Age);
}
}
}
正如您所看到的,新代码更简洁,编码错误(或拼写错误)更少。我在XAML中所要做的就是绑定到“MyPerson.V”而不是“MyPerson”。但是,由于没有任何方法可以为autoproperties实现初始化器,我必须初始化构造函数中的每个属性。在某些情况下,我跳过了初始化程序,这导致了一些运行时错误。所以,为了解决这个问题,在ViewModelBase类的构造函数中,我添加了这个循环:
public ViewModelBase()
{
foreach(var notifierProperty in this.GetType().GetProperties().Where(c=>c.PropertyType.GetInterfaces().Any(d=>d==typeof(INotifier))))
{
notifierProperty.SetValue(this, notifierProperty.PropertyType.GetConstructor(System.Type.EmptyTypes).Invoke(null), null);
}
}
这样做,无论何时实例化ViewModelBase派生类,构造函数都会遍历这些属性,并为每个Notifier类型属性调用构造函数。
这是邪恶的吗?以这种方式使用反射会在将来再次困扰我吗?我应该注意哪些性能命中?答案 0 :(得分:1)
我认为没关系。我要添加一些信息:
Activator.Create(myType)
来创建具有普通构造函数的类型,这意味着您不必获取构造函数。ReactiveProperty
的库,它定义了一个与ReactiveProperty<T>
非常相似的类Notifier<T>
。您将绑定它的Value
属性:
public class ReactiveProperty<T> : IObservable<T>, IDisposable, INotifyPropertyChanged, IReactiveProperty, INotifyDataErrorInfo
{
public T Value
{
get { return latestValue; }
set { anotherTrigger.OnNext(value); }
}
// ...
}
设置者中的呼叫最终导致对INotifyPropertyChanged.PropertyChanged
的相应呼叫。
ReactiveProperty<T>
也是reactive extensions意义上的可观察对象,库依赖于{{3}}。除此之外,作者基本上做了你做的,但没有构造函数中的初始化黑客。