2

最近、Unityアプリケーションブロックでインターセプトの使用を開始しましたが、ネストされたプロパティを取得して、ビューモデルのモデル内から変更されたことを警告するという厄介な問題があります。たとえば、System.Drawing.Pointをパブリックプロパティとして持つモードがあります。ビューモデルには、ポイントを有効で読みやすい値として表示するための文字列形式を返すパブリックプロパティがあります。ただし、インターセプトを正しく登録していないか、Unityインターセプトでは最終目標を達成できないと思います。

インターセプトをコンテナに登録し、すべての仮想メソッドをインターセプトするポリシーを設定し、設定されたすべてのイベントをキャッチするルールを設定しました。ビューモデルをトリガーしてそれを検出/認識させる方法に困惑していますが、私の人生の間モデルのプロパティが変更されました。「簡単な」解決策は、ビューモデルをモデルのプロパティに具体的にバインドし、UIでカスタムフォーマッターを使用して、値が正しく表示されるようにすることだと思います。

誰かが団結の傍受に関していくつかの指針を与えることができれば、それは壮大なことです。

Container.AddNewExtension<Interception>();

PolicyDefinition policyDefinition =
            Container.Configure<Interception>()
                .SetInterceptorFor<MyModel>(new VirtualMethodInterceptor())
                .SetInterceptorFor<MyViewModel>(new VirtualMethodInterceptor())
                .AddPolicy("NotifyPolicy");

policyDefinition.AddMatchingRule(new PropertyMatchingRule("*", PropertyMatchingOption.Set));


public class MyModel
{
    [NotifyPropertyChanged]
    public virtual Point APoint { get; set; }
}

public class MyViewModel
{
    private MyModel _myModel;

public MyViewModel()
{
        _myModel = new MyModel { APoint = new Point(3, 2) };

    // {12,8} is not reflected in the UI
    _myModel.APoint = new Point(12, 8);
    }

[NotifyPropertyChanged]
public virtual string ModelLocation
{
       get
   {
           return string.Format("'{0}, {1}'", _myModel.APoint.X, _myModel.APoint.Y);
            }
    }
}

http://www.codeproject.com/Articles/140042/Aspect-Examples-INotifyPropertyChanged-via-AspectsのNotifyPropertyChangedAttributeとNotifyPropertyChangedHandlerを例として使用して、接続しました。参照用のメソッドのみを含めました。

[AttributeUsage(AttributeTargets.Property)]
public class NotifyPropertyChangedAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new NotifyPropertyChangedHandler();
    }
}

internal class NotifyPropertyChangedHandler : ICallHandler
{
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        var result = getNext()(input, getNext);

        if (input.MethodBase.Name.StartsWith("set_"))
        {
            var propertyName = input.MethodBase.Name.Substring(4);
            var pi = input.Target.GetType().GetProperty(propertyName);

            if (pi.HasAttribute<NotifyPropertyChangedAttribute>())
            {
                var baseType = input.Target.GetType().BaseType;
                if (baseType != null)
                {
                    var info =
                        baseType.GetFields(
                            BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy)
                             .FirstOrDefault(f => f.FieldType == typeof(PropertyChangedEventHandler));

                    if (info != null)
                    {
                        var propertyChangedEventHandler = info.GetValue(input.Target) as PropertyChangedEventHandler;
                        if (propertyChangedEventHandler != null)
                            propertyChangedEventHandler.Invoke(
                                input.Target.GetType(), new PropertyChangedEventArgs(propertyName));
                    }
                }
            }
        }

        return result;
    }

    public int Order { get; set; }
}
4

1 に答える 1

3

ビュー モデルを登録するときは、仮想メソッド インターセプターを実行するだけでは不十分です。PolicyInjectionInterceptor を使用してポリシー インジェクション用に登録する必要もあります (私はそう思います)。

ただし、Unity ポリシーを必要とせずにコンパイル時に INotifyPropertyChanged 機能を提供する NotifyPropertyWeaver を検討することを真剣にお勧めします。

于 2012-12-12T21:02:02.440 に答える