http://msdn.microsoft.com/en-us/library/ff660851(v=PandP.20).aspxは、IInterceptionBehaviorを実装してINotifyPropertyChangedサポートを追加する方法のサンプルを提供します。サンプルに含まれていないものは、実行時にNotifyPropertyChangedBehaviorを使用するように設定する方法です。私がしたすべてのグーグルが、私に実用的な答えを与えていない。実行時にUnity 2.0を設定してINotifyPropertyChangedを傍受するには?
私は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;
}
}
}
あなたのコードがコンパイルされ、一見動作しますが、期待通りにPropertyChangedイベントは、お客様により提起されていません。私はソースコードをc#に変更しました。これはポストを読む人が増えているようです。 –
エラーが見つかりました。インターセプタはVirtualMethodInterceptorではなくTransparentProxyInterceptorでなければなりません。 – onof