Unity Intercepting(AOP)嵌套的虚拟属性

时间:2012-12-12 15:01:59

标签: c# unity-container aop

我最近开始在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; }
}

1 个答案:

答案 0 :(得分:3)

当您注册视图模型时,仅仅使用虚拟方法拦截器是不够的,您还需要使用PolicyInjectionInterceptor(我认为)注册它以进行策略注入。

但是,我认真地建议您查看NotifyPropertyWeaver,它将在编译时为您提供INotifyPropertyChanged功能,而无需Unity策略。