Castle Windsor拦截器阻止PropertyChanged事件

时间:2016-03-03 00:22:31

标签: c# wpf castle-windsor castle

我已经为这个问题创建了一个测试项目作为POC。

我有一个WPF应用程序,当我们在视图模型周围使用拦截器时,它会阻止事件的传播。如果我禁用所有拦截器,它可以正常工作。

以下是代码:

  

MyInterceptor.cs

public class MyInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        invocation.Proceed();
    }
}
  

IoCTestViewModel.cs

public interface IIoCTestViewModel : INotifyPropertyChanged
{
    int Number { get; }
}

public class IoCTestViewModel : IIoCTestViewModel
{
    public IoCTestViewModel()
    {
        var timer = new Timer(200);
        timer.Elapsed += (a, b) => {
            if(PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Number"));
            }
        };
        timer.Start();
    }

    public int Number
    {
        get
        {
            return new Random().Next(1, 100);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
  

IoCTest.xaml.cs

public partial class IoCTest : UserControl
{
    public IIoCTestViewModel ViewModel { get; set; }

    public IoCTest(IIoCTestViewModel viewModel)
    {
        InitializeComponent();

        DataContext = viewModel;
    }
}
  

App.xaml(片段)

        Container = new WindsorContainer();
        Container.Register(Component.For<MyInterceptor>().ImplementedBy<MyInterceptor>());
        Container.Register(Component.For<IIoCTestViewModel>().ImplementedBy<IoCTestViewModel>().Interceptors<MyInterceptor>());
        Container.Register(Component.For<IoCPage>().ImplementedBy<IoCTest>()); //IoCTest is a usercontrol

行。因此,一旦我获得了IoCTest的实例并将其添加到页面中,即使我每200ms发送PropertyChanged,我也看不到任何更改。如果我删除拦截器,一切正常。

那么我该如何解决这个问题呢?

1 个答案:

答案 0 :(得分:1)

这里的问题是,因为您将服务声明为IIoCTestViewModel,所以当您添加拦截器时,Windsor只需创建一个动态代理,将所有调用委托给您的实现类型。但是,拦截是使用合成完成的 - 一个对象委托给另一个。因此,当您使用this的发件人提升您的属性更改事件时,它与WPF认为正在观看的事件不同。

您应该像这样注册您的视图模型:

Container.Register(Component.For<IIoCTestViewModel,IoCTestViewModel>().Implemen‌​tedBy<IoCTestViewModel>().Interceptors<MyInterceptor>())

通过指定多个服务,其中一个实际上是您的实现类,Windsor将生成一个类代理 - 即拦截将使用继承完成,生成的代理继承自IoCTestViewModel。 (这在Windsor中称为类型转发)。现在,当您使用this发件人举起活动时,它正确引用了WPF正在观看的同一个实例。

有关类型转发及其对代理的影响的更详细说明,请参阅here