If I've missed this in another question I apologize; I looked for a good while before deciding I had a unique question... I want to use DynamicProxy2 to provide interception for a WPF application's model classes. This is so that I do not have to fully implement INotifyPropertyChanged everywhere. For instance, the below class should fully participate in two-way data binding once proxied and intercepted:
public class ModelExample : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int Id{ get; set; }
public string Uri{ get; set; }
public string Name{ get; set; }
}
I have found that I can create a new instance of the model class and intercept calls to it by calling the CreateClassProxy method:
new ProxyGenerator().CreateClassProxy<T>(interceptors);
Unfortunately, this forces me to allow the ProxyGenerator
class to create my model instances, and I'm getting those back from my middle tier, i.e. they already exist. I need to wrap existing objects, so I think I need to call CreateClassProxyWithTarget
instead:
new ProxyGenerator().CreateClassProxyWithTarget(instance, interceptors);
However, when I do that my interceptor stops functioning. I'm pretty sure it's not the interceptor's fault... it's a very simple object. Here's its interface:
public interface IFluentInterceptor : IInterceptor
{
IFluentInterceptor Before(Action<IInvocation> before);
IFluentInterceptor After(Action<IInvocation> after);
IFluentInterceptor Finally(Action<IInvocation> @finally);
IFluentInterceptor RunCondition(Func<IInvocation, bool> runCondition);
IFluentInterceptor OnError(Func<IInvocation, Exception, bool> onError);
}
The FluentInterceptor
type implements this. The Before
, After
, etc. methods are too simple to show; they all add to action queues that are meant to be used during method invocation, then each method returns this
, allowing for method chaining.
The below code doesn't work, but I can't figure out why:
new ProxyGenerator().CreateClassProxyWithTarget(instance, new FluentInterceptor()
.After(invocation =>
{
if (!invocation.Method.Name.StartsWith("set_")) return;
string propertyName = invocation.Method.Name.Substring(4);
FieldInfo info = invocation.TargetType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
.Where(f => f.FieldType.Equals(typeof (PropertyChangedEventHandler)))
.FirstOrDefault();
if (info == null) return;
var handler = info.GetValue(invocation.InvocationTarget) as PropertyChangedEventHandler;
if (handler != null) handler.Invoke(invocation.TargetType, new PropertyChangedEventArgs(propertyName));
}));
If I try that with CreateClassProxy
, it works like a charm. Does anybody see what I'm doing wrong?
Thanks!