使用Reflection初始化对象的autoproperties - 任何警告?

时间:2014-01-27 15:50:34

标签: c# wpf silverlight reflection

我最近编写了两个类和一个接口作为实现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类型属性调用构造函数。

这是邪恶的吗?以这种方式使用反射会在将来再次困扰我吗?我应该注意哪些性能命中?

1 个答案:

答案 0 :(得分:1)

我认为没关系。我要添加一些信息:

  1. 您可以通过调用Activator.Create(myType)来创建具有普通构造函数的类型,这意味着您不必获取构造函数。
  2. 我相信至少对于Silverlight来说,用你的hack初始化的所有属性都需要公开。
  3. 有一个名为ReactiveProperty的库,它定义了一个与ReactiveProperty<T>非常相似的类Notifier<T>
  4. 您将绑定它的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}}。除此之外,作者基本上做了你做的,但没有构造函数中的初始化黑客。