Castle Windsor代理、隐式接口和WPF绑定

Castle Windsor代理、隐式接口和WPF绑定,wpf,binding,castle-windsor,ioc-container,castle-dynamicproxy,Wpf,Binding,Castle Windsor,Ioc Container,Castle Dynamicproxy,我正在尝试使用Castle Windsor动态代理实现WPF ViewModel。我的想法是,我想提供一个接口(下面的IPerson应足以作为示例)、一个具体的支持类和一个拦截器(用于提供INotifyPropertyChanged的自动实现)。拦截器的实现如下: 我看到的问题是,当我将模型绑定到WPF控件时,这些控件并不认为模型实现了INotifyPropertyChanged。我相信(但不确定)这是因为Windsor正在显式地实现接口,而WPF似乎期望它们是隐式的 是否有任何方法可以实现这一

我正在尝试使用Castle Windsor动态代理实现WPF ViewModel。我的想法是,我想提供一个接口(下面的IPerson应足以作为示例)、一个具体的支持类和一个拦截器(用于提供INotifyPropertyChanged的自动实现)。拦截器的实现如下:

我看到的问题是,当我将模型绑定到WPF控件时,这些控件并不认为模型实现了INotifyPropertyChanged。我相信(但不确定)这是因为Windsor正在显式地实现接口,而WPF似乎期望它们是隐式的

是否有任何方法可以实现这一点,以便拦截器捕获对模型的更改并将其提升到模型

所有版本的库都是最新的:Castle.Core 2.5.1.0和Windsor 2.5.1.0

代码如下:

// My model's interface
public interface IPerson : INotifyPropertyChanged
{
    string First { get; set; }
    string LastName { get; set; }
    DateTime Birthdate { get; set; }
}

// My concrete class:
[Interceptor(typeof(NotifyPropertyChangedInterceptor))]
class Person : IPerson
{
    public event PropertyChangedEventHandler PropertyChanged = (s,e)=> { };
    public string First { get; set; }
    public string LastName { get; set; }
    public DateTime Birthdate { get; set; }
}

// My windsor installer
public class Installer : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component.For<NotifyPropertyChangedInterceptor>()
            .ImplementedBy<NotifyPropertyChangedInterceptor>()
            .LifeStyle.Transient);
        container.Register(
            Component.For<IPerson, INotifyPropertyChanged>()
            .ImplementedBy<Person>().LifeStyle.Transient);
    }
}
//我的模型的接口
公共接口IPerson:INotifyPropertyChanged
{
第一个字符串{get;set;}
字符串LastName{get;set;}
日期时间出生日期{get;set;}
}
//我的具体课程:
[拦截器(类型(NotifyPropertyChangedInterceptor))]
课程负责人:IPerson
{
公共事件PropertyChangedEventHandler PropertyChanged=(s,e)=>{};
第一个公共字符串{get;set;}
公共字符串LastName{get;set;}
公共日期时间出生日期{get;set;}
}
//我的温莎安装程序
公共类安装程序:IWindsorInstaller
{
public void安装(IWindsorContainer、IConfigurationStore)
{
集装箱。登记(
用于()的组件
.由()实施
(生活方式,短暂),;
集装箱。登记(
用于()的组件
.ImplementedBy().lifesture.Transient);
}
}

我认为您需要使实现接口的类的成员成为虚拟的。

因此答案非常简单。。。中的代码将拦截器定义为:

public class NotifyPropertyChangedInterceptor : IInterceptor
{
    private PropertyChangedEventHandler _subscribers = delegate { };

    public void Intercept(IInvocation invocation)
    {
        if (invocation.Method.DeclaringType == typeof(INotifyPropertyChanged))
        {
            HandleSubscription(invocation);
            return;
        }

        invocation.Proceed();

        if (invocation.Method.Name.StartsWith("set_"))
        {
            FireNotificationChanged(invocation);
        }
    }

    private void HandleSubscription(IInvocation invocation)
    {
        var handler = (PropertyChangedEventHandler)invocation.Arguments[0];

        if (invocation.Method.Name.StartsWith("add_"))
        {
            _subscribers += handler;
        }
        else
        {
            _subscribers -= handler;
        }
    }

    private void FireNotificationChanged(IInvocation invocation)
    {
        var propertyName = invocation.Method.Name.Substring(4);
        _subscribers(invocation.InvocationTarget, new PropertyChangedEventArgs(propertyName));
    }
}
在我的例子中,InvocationTarget根本不是作为PropertyChanged的第一个参数传递的正确实体(因为我正在生成代理)。将最后一个函数更改为以下值修复了该问题:

private void FireNotificationChanged(IInvocation invocation)
{
    var propertyName = invocation.Method.Name.Substring(4);
    _subscribers(invocation.Proxy, new PropertyChangedEventArgs(propertyName));
}