Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance advice for using Castle DynamicProxy in .NET web-apps

I am starting out with Castle DynamicProxy and I have this sample to track changes to properties of an object.

Questions:

  • Should I cache (in a static field) the ProxyGenerator() instance I use in AsTrackable()? I going to use in an ASP.NET web-app, and I was not sure if the class is thread-safe? Is it expensive to create?
  • If I leave the code as is, will the generated proxy types be re-used by the different ProxyGenerator instances. I read the caching tutorial, but not sure what "module scope" means.
  • Is there any other advice from a performance standpoint to improve the code?

Code:

class Program
{
    static void Main(string[] args)
    {
        var p = new Person { Name = "Jay" }.AsTrackable();

        //here's changed properties list should be empty.
        var changedProperties = p.GetChangedProperties();

        p.Name = "May";

        //here's changed properties list should have one item.
        changedProperties = p.GetChangedProperties();
    }
}

public static class Ext
{
    public static T AsTrackable<T>(this T instance) where T : class
    {
        return new ProxyGenerator().CreateClassProxyWithTarget
        (
          instance, 
          new PropertyChangeTrackingInterceptor()
        );
    }

    public static HashSet<string> GetChangedProperties<T>(this T instance) 
    where T : class
    {
        var proxy = instance as IProxyTargetAccessor;

        if (proxy != null)
        {
            var interceptor = proxy.GetInterceptors()
                                   .Select(i => i as IChangedProperties)
                                   .First();

            if (interceptor != null)
            {
                return interceptor.Properties;
            }
        }

        return new HashSet<string>();
    }
}

interface IChangedProperties
{
    HashSet<string> Properties { get; }
}

public class PropertyChangeTrackingInterceptor : IInterceptor, IChangedProperties
{
    public void Intercept(IInvocation invocation)
    {
        invocation.Proceed();

        this.Properties.Add(invocation.Method.Name);
    }

    private HashSet<string> properties = new HashSet<string>();

    public HashSet<string> Properties
    {
        get { return this.properties; }
        private set { this.properties = value; }
    }
}

public class Person
{
    public virtual string Name { get; set; }
    public virtual int Age { get; set; }
}

}

like image 581
Raghu Dodda Avatar asked Jun 10 '11 06:06

Raghu Dodda


1 Answers

It is thread-safe to cache a static copy of your proxy generator and you absolutely should do this. That is considered best-practice with this API and not doing so will result in extra types defined in new dynamic assemblies for no reason.

like image 164
Kirk Woll Avatar answered Sep 19 '22 03:09

Kirk Woll