Cru代码。 IoC来救援

关于IoC Container的实用性问题 ,获奖提交者提到,使用IoC容器,您可以采取以下措施:

public class UglyCustomer : INotifyPropertyChanged { private string _firstName; public string FirstName { get { return _firstName; } set { string oldValue = _firstName; _firstName = value; if(oldValue != value) OnPropertyChanged("FirstName"); } } private string _lastName; public string LastName { get { return _lastName; } set { string oldValue = value; _lastName = value; if(oldValue != value) OnPropertyChanged("LastName"); } } } 

对此:

 var bindingFriendlyInstance = IoC.Resolve(new NotifyPropertyChangedWrapper()); 

问题:

  • 哪个神奇的IoC容器提供了这种优点?
  • 实现这个的一个例子?
  • 有任何缺点吗?
  • 在具有复杂依赖关系的项目中,当我尝试将数据绑定应用于这些对象时,我会哭吗?

为了使您的第二个代码片段起作用, NotifyPropertyChangedWrapper肯定必须使用reflection(或dynamic )来生成一个类,该类提供与Customer兼容的接口并实现自动属性通知。 不应该有任何数据绑定问题,但会有一点开销。

使用动态对象的简化实现可能如下所示:

 public class NotifyPropertyChangedWrapper : DynamicObject, INotifyPropertyChanged { private T _obj; public NotifyPropertyChangedWrapper(T obj) { _obj = obj; } public override bool TryGetMember( GetMemberBinder binder, out object result) { result = typeof(T).GetProperty(binder.Name).GetValue(_obj); return true; } // If you try to set a value of a property that is // not defined in the class, this method is called. public override bool TrySetMember( SetMemberBinder binder, object value) { typeof(T).GetProperty(binder.Name).SetValue(_obj, value); OnPropertyChanged(binder.Name); return true; } // Implement OnPropertyChanged... } 

显然,任何使用其中一个对象的代码都会失去任何静态类型安全性。 另一种选择是生成一个实现与被包装的类相同的接口的类。 网上有很多这方面的例子。 主要要求是您的Customer必须是一个interface或者它需要所有属性都是虚拟的。

要以通用方式执行此操作(即,为任何类实现INotifyPropertyChanged的单个代码),请使用代理。 使用Castle.DynamicProxy或LinFu或Unity有很多实现。 这些代理库在IoC容器中具有良好的支持,例如DynamicProxy与Castle Windsor的良好集成,Unity拦截(或其他任何调用)显然与Unity容器的良好集成。

我从来没有使用它,但你可以使用PostSharp创建这样的东西。

如果您正在寻找自动生成可绑定对象的特定解决方案,您应该查看PropertyChanged.Fody (以前是NotifyPropertyWeaver)。 这将重写实现INotifyPropertyChanged的类以包含通知代码。 github页面上有一个例子。

在我看来,这比使用提议的IOC容器解决方案更整洁。 但是,它是一个特定于INotifyPropertyChanged绑定的库,因此不适用于一般解决方案,正如您在链接问题中所讨论的那样。