-
Notifications
You must be signed in to change notification settings - Fork 479
Open
Description
This is a simplified version of what I am doing, but this should be enough to explain.
I want to add INotifyPropertyChanged to a POCO (Blog) class,
and I want to raise PropertyChanged even if the property is changed by a method on the Target (SetBlogId()), this no longer works after 5.0.0 probably because #571 changed the SetBlogId() execution to be on the target not on the proxy.
Is there any way I can invoke the target.Method() on the Proxy?
in 4.4.1 the output is
Change event was raised as expected
in 5.0.0 the output is
Expected a change event
using System;
using Castle.DynamicProxy;
using System.ComponentModel;
using System.Reflection;
internal class Program
{
private static void Main(string[] args)
{
Blog blog = new Blog();
ProxyGenerator generator = new ProxyGenerator();
Blog proxy = (Blog)generator.CreateClassProxyWithTarget(
classToProxy: typeof(Blog),
additionalInterfacesToProxy: new[] { typeof(INotifyPropertyChanged) },
options: new ProxyGenerationOptions(new PropertiesOnlyGenerationHook()),
target: blog,
interceptors: new INotifyPropertyChangedInterceptor());
bool propertyChangedEventRaised = false;
((INotifyPropertyChanged)proxy).PropertyChanged += (o, e) => propertyChangedEventRaised = true;
proxy.SetBlogId(1000);
Console.WriteLine(propertyChangedEventRaised ? "Change event was raised as expected" : "Expected a change event");
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
internal class PropertiesOnlyGenerationHook : IProxyGenerationHook
{
public void MethodsInspected() { }
public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo) { }
// intercept propery and event setters
public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo) => methodInfo.IsSpecialName;
}
internal class INotifyPropertyChangedInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
if (invocation.Method.Name.StartsWith("set_", StringComparison.Ordinal))
{
string propertyName = invocation.Method.Name["set_".Length..];
invocation.Proceed();
PropertyChanged?.Invoke(invocation.Proxy, new PropertyChangedEventArgs(propertyName));
}
else if (invocation.Method.Name == "add_PropertyChanged")
{
PropertyChanged += (PropertyChangedEventHandler)invocation.Arguments[0];
}
else if (invocation.Method.Name == "remove_PropertyChanged")
{
PropertyChanged -= (PropertyChangedEventHandler)invocation.Arguments[0];
}
else
{
invocation.Proceed();
}
}
private event PropertyChangedEventHandler? PropertyChanged;
}
public class Blog
{
public virtual int BlogId { get; set; }
public virtual void SetBlogId(int blogId) => BlogId = blogId;
}Metadata
Metadata
Assignees
Labels
No labels