首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在运行时配置Unity2.0来拦截INotifyPropertyChanged?

如何在运行时配置Unity2.0来拦截INotifyPropertyChanged?
EN

Stack Overflow用户
提问于 2010-11-29 18:59:50
回答 3查看 3.1K关注 0票数 2

http://msdn.microsoft.com/en-us/library/ff660851(v=PandP.20).aspx提供了一个如何实现IInterceptionBehavior以添加INotifyPropertyChanged支持的示例。该示例没有包括如何配置在运行时使用的NotifyPropertyChangedBehavior。我所做的所有谷歌搜索都没有给我一个有效的答案。

我是AOP和IoC的新手,所以可能我的概念也是错的。这就是我想要做的:

代码语言:javascript
复制
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;

static class AppMain
{
    public static void Main()
    {
        // Configure Unity.
        var container = new UnityContainer();

        container.AddNewExtension<Interception>();

        // todo: Register an interface instead of a type.
        container.RegisterType<Customer>(new Interceptor<VirtualMethodInterceptor>(), 
                                         new InterceptionBehavior<NotifyPropertyChangedBehavior>());

        var propertyChangedCount = 0;
        var customer = new Customer();

        customer.PropertyChanged += (s, e) => propertyChangedCount += 1;

        // Update customer and send property changed event.
        customer.FirstName = "what ever";

        if (propertyChangedCount != 1)
        {
            Console.Write("Failed!");
        }
        else
        {
            Console.WriteLine("Success!");
        }

        Console.WriteLine();
        Console.WriteLine("Press any key to continue...");
        Console.ReadKey();

    }

    static void customer_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        throw new NotImplementedException();
    }

    public class Customer : MarshalByRefObject, INotifyPropertyChanged
    {

        private string _firstName;
        public event PropertyChangedEventHandler PropertyChanged;

        // todo: Does the property have to be virtual (overridable).
        public virtual string FirstName
        {
            get { return _firstName; }
            set
            {
                _firstName = value;
                // Unity Interception to do the following RaiseEvent
                //if (PropertyChanged != null)
                //{
                //    PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
                //}
            }
        }

    }

    // Copied from http://msdn.microsoft.com/en-us/library/ff660851(v=PandP.20).aspx
    class NotifyPropertyChangedBehavior : IInterceptionBehavior
    {
        private event PropertyChangedEventHandler propertyChanged;

        private static readonly MethodInfo addEventMethodInfo =
            typeof(INotifyPropertyChanged).GetEvent("PropertyChanged").GetAddMethod();

        private static readonly MethodInfo removeEventMethodInfo =
            typeof(INotifyPropertyChanged).GetEvent("PropertyChanged").GetRemoveMethod();

        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {
            if (input.MethodBase == addEventMethodInfo)
            {
                return AddEventSubscription(input, getNext);
            }
            if (input.MethodBase == removeEventMethodInfo)
            {
                return RemoveEventSubscription(input, getNext);
            }
            if (IsPropertySetter(input))
            {
                return InterceptPropertySet(input, getNext);
            }
            return getNext()(input, getNext);
        }

        public bool WillExecute
        {
            get { return true; }
        }

        public IEnumerable<Type> GetRequiredInterfaces()
        {
            return new[] { typeof(INotifyPropertyChanged) };
        }

        private IMethodReturn AddEventSubscription(IMethodInvocation input, 
                                                   GetNextInterceptionBehaviorDelegate getNext)
        {
            var subscriber = (PropertyChangedEventHandler)input.Arguments[0];

            propertyChanged += subscriber;
            return input.CreateMethodReturn(null);
        }

        private IMethodReturn RemoveEventSubscription(IMethodInvocation input, 
                                                      GetNextInterceptionBehaviorDelegate getNext)
        {
            var subscriber = (PropertyChangedEventHandler)input.Arguments[0];

            propertyChanged -= subscriber;
            return input.CreateMethodReturn(null);
        }

        private static bool IsPropertySetter(IMethodInvocation input)
        {
            return input.MethodBase.IsSpecialName && input.MethodBase.Name.StartsWith("set_");
        }

        private IMethodReturn InterceptPropertySet(IMethodInvocation input, 
                                                   GetNextInterceptionBehaviorDelegate getNext)
        {
            var propertyName = input.MethodBase.Name.Substring(4);
            var returnValue = getNext()(input, getNext);
            var subscribers = propertyChanged;

            if (subscribers != null)
            {
                subscribers(input.Target, new PropertyChangedEventArgs(propertyName));
            }

            return returnValue;
        }
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-11-30 08:29:50

时间

难道一些IL编织不会让这件事变得更容易吗?

NotifyPropertyWeaver还是http://www.sharpcrafters.com/

票数 2
EN

Stack Overflow用户

发布于 2010-11-29 22:21:20

herehere。基本上,您必须注册类型和拦截器:

代码语言:javascript
复制
Dim container As IUnityContainer = New UnityContainer()
   container.AddNewExtension(Of Interception)()
   container.RegisterType(Of Customer)( _
          New Interceptor(Of VirtualMethodInterceptor)(), _
          New InterceptionBehavior(Of NotifyPropertyChangedBehavior)())
票数 1
EN

Stack Overflow用户

发布于 2014-07-08 04:47:01

我需要使用VirtualMethodInterceptor。我发现对PropertyChanged添加或删除的NotifyPropertyChangedBehavior.Invoke检查从来都不是真的。我更改为检查方法名是否匹配,一切正常。

原始的NotifyPropertyChangedBehavior来自于msdn上的Unity文档。如果有人能告诉我为什么原始代码不能工作,我很感兴趣。

类定义

代码语言:javascript
复制
public class NotifyPropertyChangeClass 
    : INotifyPropertyChanged
{
    public virtual int SomeInt { get; set; }

    public virtual event PropertyChangedEventHandler PropertyChanged;
}

IUnityContainer设置

代码语言:javascript
复制
container.AddNewExtension<Interception>();
container.RegisterType<NotifyPropertyChangeClass>(
    new Interceptor<VirtualMethodInterceptor>(),
    new InterceptionBehavior(new NotifyPropertyChangedBehavior()));

NotifyPropertyChangedBehavior修改(original)

代码语言:javascript
复制
public class NotifyPropertyChangedBehavior : IInterceptionBehavior
{
...
    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        if (input.MethodBase.Name.Equals(addEventMethodInfo.Name))//(input.MethodBase == addEventMethodInfo)
        {
            return AddEventSubscription(input, getNext);
        }
        if (input.MethodBase.Name.Equals(removeEventMethodInfo.Name))//(input.MethodBase == removeEventMethodInfo)
        {
            return RemoveEventSubscription(input, getNext);
        }
        if (IsPropertySetter(input))
        {
            return InterceptPropertySet(input, getNext);
        }
        return getNext()(input, getNext);
    }
...
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4303083

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档