3

Castle Windsor Dynamic Proxies を使用して 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);
    }
}
4

2 に答える 2

4

したがって、答えはかなり単純であることがわかりました... 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));
}
于 2011-05-09T14:54:04.153 に答える
0

インターフェイス Virtual を実装するクラスのメンバーを作成する必要があると思います。

于 2011-05-07T04:37:35.477 に答える