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...)

1

There are 1 answers

0
Seven On BEST ANSWER

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);
        }
    }
}