1

I'd like to create a method that does the following:

  1. Takes an arbitrary instance as parameter
  2. Generates a wrapper instance providing all properties and methods in the same way as the passed instance
  3. Overrides one method with a different implementation
  4. Returns that generated instance

This is something quite similar to the proxy objects that ORMs create. They normally do not return the real model classes, but proxy objects that behave the same ways, except for lazy loading, etc.

Is there something suitable out there? (I saw CodeDom, but also saw the opcodes I need to emit for a method implementation...)

Zong
  • 6,160
  • 5
  • 32
  • 46
Seven
  • 4,353
  • 2
  • 27
  • 30
  • CodeDom doesn't use opcodes; that's `Reflection.Emit`. – Jeroen Vannevel Jun 06 '14 at 15:30
  • @Jeroen: Jep, you're right. Should read: 'saw the too simple examples for CodeMethodInvokeExpression, and OpCodes for Emit' ;-) – Seven Jun 06 '14 at 15:34
  • 1
    If the instance is instance of public class and the method is virtual you can use RhinoMocks for this - why reinvent the wheel ? – Ondrej Svejdar Jun 06 '14 at 15:52
  • possible duplicate of [Dynamically creating a proxy class](http://stackoverflow.com/questions/15733900/dynamically-creating-a-proxy-class) – Ben Aaronson Jun 06 '14 at 16:29
  • @BenAaronson: Your link seemed to match and the solution looked really like I would have expected. However, deriving my classes from MarshalByRefObject yields problems at other locations. – Seven Jun 11 '14 at 08:44
  • @Seven Not sure about that I'm afraid. Might warrant its own question. – Ben Aaronson Jun 11 '14 at 08:48

1 Answers1

1

Thank you for all the hints and links. Castle Project's DynamicProxy (http://www.castleproject.org/projects/dynamicproxy/) did the job for me.

A proxy generator just overriding a single method (in this case GetHashCode()) was done with ease:

/// <summary>
/// A class that is capable to wrap arbitrary objects and "override" method GetHashCode()
/// This is suitable for object that need to be passed to any WPF UI classes using them in
/// a hashed list, set of other collection using hash codes.
/// </summary>
public class CustomProxyFactory
{
    /// <summary>
    /// Interceptor class that stores a static hash code, "overrides" the
    /// method GetHashCode() and returns this static hash code instead of the real one
    /// </summary>
    public class HashCodeInterceptor : IInterceptor
    {
        private readonly int frozenHashCode;

        public HashCodeInterceptor( int frozenHashCode )
        {
            this.frozenHashCode = frozenHashCode;
        }

        public void Intercept( IInvocation invocation )
        {
            if (invocation.Method.Name.Equals( "GetHashCode" ) == true)
            {
                invocation.ReturnValue = this.frozenHashCode;
            }
            else
            {
                invocation.Proceed();
            }
        }
    }

    /// <summary>
    /// Factory method
    /// </summary>
    /// <param name="instance">Instance to be wrapped by a proxy</param>
    /// <returns></returns>
    public static T Create<T>( T instance ) where T : class
    {
        try
        {
            IInterceptor hashCodeInterceptor = new HashCodeInterceptor( instance.GetHashCode() );
            IInterceptor[] interceptors = new IInterceptor[] {hashCodeInterceptor};

            ProxyGenerator proxyGenerator = new ProxyGenerator();
            T proxy = proxyGenerator.CreateClassProxyWithTarget( instance, interceptors );

            return proxy;
        }
        catch (Exception ex)
        {
            Console.WriteLine( typeof(CustomProxyFactory).Name + ": Exception during proxy generation: " + ex );
            return default(T);
        }
    }
}
Seven
  • 4,353
  • 2
  • 27
  • 30