c# - CaSTLe Windsor 拦截器阻止 PropertyChanged 事件

标签 c# wpf castle-windsor castle

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

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

代码如下:

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 (fragment)

        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。如果我删除拦截器,一切正常。

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

最佳答案

这里的问题是,因为您将服务声明为 IoCTestViewModel,所以当您添加拦截器时,Windsor 只会创建一个动态代理,将所有调用委托(delegate)给您的实现类型。但是,拦截是使用组合完成的——一个对象委托(delegate)给另一个对象。因此,当您使用 this 的发送者引发属性更改事件时,它是与 WPF 认为它正在监视的对象不同的对象。

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

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

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

参见 here有关类型转发及其对代理的影响的更详细解释

关于c# - CaSTLe Windsor 拦截器阻止 PropertyChanged 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35760855/

相关文章:

c# - 具有从工厂方法创建的私有(private)构造函数的单元测试类

javascript - 如何在asp :gridview using javascript上访问同一行上的其他文本框

c# - 如何绑定(bind)一个只读的 WPF 控件属性(例如 ActualWidth)以便在 View 模型中可以访问它的值?

design-patterns - 我们是否有效地使用了 IoC?

c# - Controller 的 Action 在具有相同名称的基类的 Action 之间是不明确的。

c# - Intellisense 不显示存储在外部文件中的 XML 注释

c# - ASP.NET Web API 的 CaSTLe Windsor ApiController Factory 实现

caSTLe-windsor - 替换 CaSTLe Windsor 中过时的 AllTypes 类

wpf - 在 WPF 中为电话号码设置文本框格式

c# - Wpf\MVVM - 我应该在哪里放置 View 相关属性?