【问题标题】:Castle Windsor proxies, implicit interfaces and WPF BindingCastle Windsor 代理、隐式接口和 WPF 绑定
【发布时间】:2023-03-03 17:09:01
【问题描述】:

我正在尝试使用 Castle Windsor 动态代理来实现 WPF ViewModel。这个想法是我想提供一个接口(下面的 IPerson 应该足以作为示例)、一个具体的支持类和一个拦截器(用于提供 INotifyPropertyChanged 的​​自动实现)。拦截器实现在这里:http://www.hightech.ir/SeeSharp/Best-Implementation-Of-INotifyPropertyChange-Ever

我看到的问题是,当我将模型绑定到 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);
    }
}

【问题讨论】:

    标签: wpf binding castle-windsor ioc-container castle-dynamicproxy


    【解决方案1】:

    所以答案非常简单......来自http://www.hightech.ir/SeeSharp/Best-Implementation-Of-INotifyPropertyChange-Ever 的代码将拦截器定义为:

    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));
    }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2011-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-20
        • 2014-08-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多