【问题标题】:Generate proxy objects on the fly (programmatically generate class derived from given object and override single method)动态生成代理对象(以编程方式生成从给定对象派生的类并覆盖单个方法)
【发布时间】:2014-06-06 15:26:23
【问题描述】:

我想创建一个执行以下操作的方法:

  1. 将任意实例作为参数
  2. 生成一个包装器实例,以与传递的实例相同的方式提供所有属性和方法
  3. 用不同的实现覆盖一个方法
  4. 返回生成的实例

这与 ORM 创建的代理对象非常相似。它们通常不返回真实的模型类,而是行为相同的代理对象,除了延迟加载等。

那里有合适的东西吗? (我看到了 CodeDom,但也看到了我需要为方法实现发出的操作码......)

【问题讨论】:

  • CodeDom 不使用操作码;那是Reflection.Emit
  • @Jeroen:杰普,你是对的。应该阅读:'看到 CodeMethodInvokeExpression 的过于简单的示例,以及 Emit 的 OpCodes' ;-)
  • 如果实例是公共类的实例并且方法是虚拟的,您可以为此使用 RhinoMocks - 为什么要重新发明轮子?
  • @BenAaronson:您的链接似乎匹配,并且解决方案看起来真的像我预期的那样。但是,从 MarshalByRefObject 派生我的类会在其他位置产生问题。

标签: c# proxy-object


【解决方案1】:

感谢您提供的所有提示和链接。 Castle Project 的 DynamicProxy (http://www.castleproject.org/projects/dynamicproxy/) 为我完成了这项工作。

只覆盖单个方法(在本例中为 GetHashCode())的代理生成器很容易完成:

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

【讨论】:

    猜你喜欢
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    • 2010-09-22
    • 2022-08-03
    • 2022-08-18
    • 1970-01-01
    相关资源
    最近更新 更多