22

关于IoC 容器的有用性的问题,获胜的提交者提到,使用 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<Customer>(new NotifyPropertyChangedWrapper()); 

问题:

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

4 回答 4

9

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

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

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...
}

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

于 2010-12-14T02:28:52.210 回答
3

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

于 2010-12-14T05:00:14.907 回答
3

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

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

于 2013-07-02T10:08:20.543 回答
2

我从未使用过它,但据说您可以使用PostSharp创建类似的东西。

于 2010-12-14T02:28:40.147 回答