2016-03-03 122 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爲轉發類型的更詳細的解釋及其代理人