2016-03-03 124 views
2

我已经创建了一个测试项目作为此问题的POC。Castle Windsor拦截器阻止PropertyChanged事件

我有一个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的一个实例并将其添加到页面中,即使我每200毫秒发送一次PropertyChanged,我也没有看到任何更改。如果我删除拦截器,一切正常。

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

+0

的影响,我相信你的PropertyChange通知正在发生,但他们有错误的来源。您正在传递'this'(即您的'IoCTestViewModel'),但WPF一无所知,并且不会观察它的变化 - 它将观察温莎产生的代理。 –

+0

我认为同样的问题在这里介绍:http://stackoverflow.com/questions/5918707/castle-windsor-proxies-implicit-interfaces-and-wpf-binding –

+0

@PhilDegenhardt我相信你是正确的。任何想法如何解决它?你发布的链接是一个实现,以避免INPC代码在类,我不想。我也试过这个解决方案,但它没有奏效。 – CamronBute

回答

1

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

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

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

通过指定多种服务,其中一个是真正的实现类,温莎反而会产生一类代理 - 即拦截将用做继承,生成的代理从IoCTestViewModel继承。 (这在Windsor中称为转发类型)。现在,当您通过this的发件人举报事件时,它正确地指向WPF正在观看的同一个实例。

here为转发类型的更详细的解释及其代理人