Cruft code. IoC to the rescue
关于IOC容器的实用性,获奖提交人提到,使用IOC容器,您可以:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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"); } } } |
对此:
1 |
问题:
- 哪个神奇的IOC容器提供了这种好处?
- 实现这个的例子?
- 有什么不利因素吗?
- 在一个依赖关系复杂的项目中,当我试图将数据绑定应用到这些对象时,我会哭吗?
为了让第二个代码段正常工作,
使用动态对象的简化实现可能如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public class NotifyPropertyChangedWrapper<T> : 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... } |
显然,任何使用这些对象之一的代码都将失去任何静态类型的安全性。另一个选项是生成一个实现与被包装的类相同接口的类。网上有很多这样的例子。主要要求是,您的
以一种通用的方式(即实现inotifyPropertiesChanged的一段代码对于任何类)使用代理。有很多实现可以用castle.dynamicproxy或linfu或Unity来实现。这些代理库在IOC容器中有很好的支持,例如dynamicproxy与castle windsor有很好的集成,Unity Interception(或不管它叫什么)显然与Unity容器有很好的集成。
我从来没有用过它,但是你可以用postsharp创建类似的东西。
如果您正在为自动生成可绑定对象寻找特定的解决方案,那么您应该查看propertychanged.fody(以前是notifypropertyweaver)。这将重写实现inotifyPropertyChanged的类,以包括通知代码。Github页面上有一个示例。
在我看来,这比使用提议的IOC容器解决方案更整洁。但是,它是一个特定于inotifyPropertyChanged绑定的库,因此不适用于一般的解决方案,正如在链接问题中讨论的那样。