http://msdn.microsoft.com/en-us/library/ff660851(v=PandP.20).aspx提供了如何实现IInterceptionBehavior以添加INotifyPropertyChanged支持的示例。示例不包括如何配置要在运行时使用的NotifyPropertyChangedBehavior。我所做的所有谷歌搜索都没有给我一个合适的答案。
我是AOP和IoC的新手,所以也许我的概念也错了。这就是我想要做的事情:
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;
}
}
}
答案 0 :(得分:2)
答案 1 :(得分:1)
Dim container As IUnityContainer = New UnityContainer()
container.AddNewExtension(Of Interception)()
container.RegisterType(Of Customer)( _
New Interceptor(Of VirtualMethodInterceptor)(), _
New InterceptionBehavior(Of NotifyPropertyChangedBehavior)())
答案 2 :(得分:0)
我需要使用VirtualMethodInterceptor。我发现NotifyPropertyChangedBehavior.Invoke检查PropertyChanged添加或删除从来都不是真的。我改为检查方法名称匹配和事情是否有效。
原始NotifyPropertyChangedBehavior来自msdn上的Unity文档。我很感兴趣,如果有人能告诉我为什么原始代码不起作用。
班级定义
public class NotifyPropertyChangeClass
: INotifyPropertyChanged
{
public virtual int SomeInt { get; set; }
public virtual event PropertyChangedEventHandler PropertyChanged;
}
IUnityContainer设置
container.AddNewExtension<Interception>();
container.RegisterType<NotifyPropertyChangeClass>(
new Interceptor<VirtualMethodInterceptor>(),
new InterceptionBehavior(new NotifyPropertyChangedBehavior()));
NotifyPropertyChangedBehavior修改(original)
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);
}
...
}