动态创建一个代理类 [英] Dynamically creating a proxy class

查看:211
本文介绍了动态创建一个代理类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想动态创建一个代理类。我知道有一些很不错的框架,在那里要做到这一点,但是这纯粹是一个宠物项目作为一个学习锻炼,想自己做。

I am trying to create a proxy class dynamically. I know there are some very good frameworks out there to do this but this is purely a pet project as a learning exercise so would like to do it myself.

如果,例如,我有以下类实现一个接口:

If, for example, I have the following class implementing an interface:

interface IMyInterface
{
    void MyProcedure();
}

Class MyClass : IMyInterface
{
    void MyProcedure()
    {
        Console.WriteLine("Hello World");
    }
}

要拦截的方法来这个类,以记录他们,我创造另一个类(我的版本的代理类),它实现了相同的接口,但包含一个引用真正的类。该类执行操作(如日志记录),然后调用真正的类相同的方法。

To intercept methods to this class in order to log them, I am creating another class (my version of a proxy class) which implements the same interface but contains a reference to the 'real' class. This class performs an action (e.g. logging) and then calls the same method on the real class.

例如:

Class ProxyClass : IMyInterface
{
    private IMyInterface RealClass { get; set; }

    void MyProcedure()
    {
        // Log the call
        Console.WriteLine("Logging..");

        // Call the 'real' method
        RealClass.MyProcedure();
    }
}

呼叫者然后调用代理类的所有方法,而不是(我使用的是基本的家庭酿造IoC容器的代理类来代替真正的类的注入)。我使用这种方法,因为我希望能够换出 RealClass 在运行时另一个类实现相同的接口。

The caller then calls all methods on the proxy class instead (I am using a basic home-brew IoC container to inject the proxy class in place of the real class). I am using this method because I would like to be able to swap out RealClass at run time to another class implementing the same interface.

有没有一种方法来创建 ProxyClass 在运行时,填充它的 RealClass 属性,因此它可以作为对于真正的类代理?有没有一种简单的方法来做到这一点还是我需要使用类似 Reflection.Emit的并生成MSIL?

Is there a way to create ProxyClass at run time and populate its RealClass property so it can be used as a proxy for the real class? Is there a simple way to do this or do I need to use something like Reflection.Emit and generate the MSIL?

推荐答案

看一看<一href="http://msdn.microsoft.com/en-us/library/system.runtime.remoting.proxies.realproxy.aspx">System.Runtime.Remoting.Proxies.RealProxy.您可以使用它来创建,似乎是从调用者的角度来看,目标类型的实例。 RealProxy.Invoke提供了一个点,您可以简单地调用底层的类型目标的方法或呼叫前/后执行额外的处理(日志等)。

Have a look at System.Runtime.Remoting.Proxies.RealProxy. You can use this to create an instance that appears to be the target type from the perspective of the caller. RealProxy.Invoke provides a point from which you can simply invoke the target method on the underlying type or perform additional processing before/after the call (logging, for example).

下面是一个代理,登录到控制台的例子前/每个方法调用后:

Here's an example of a proxy that logs to the console before/after each method invocation:

public class LoggingProxy<T> : RealProxy
{
    private readonly T _instance;

    private LoggingProxy(T instance)
        : base(typeof(T))
    {
        _instance = instance;
    }

    public static T Create(T instance)
    {
        return (T)new LoggingProxy<T>(instance).GetTransparentProxy();
    }

    public override IMessage Invoke(IMessage msg)
    {
        var methodCall = (IMethodCallMessage)msg;
        var method = (MethodInfo)methodCall.MethodBase;

        try
        {
            Console.WriteLine("Before invoke: " + method.Name);
            var result = method.Invoke(_instance, methodCall.InArgs);
            Console.WriteLine("After invoke: " + method.Name);
            return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception: " + e);
            if (e is TargetInvocationException && e.InnerException != null)
            {
                return new ReturnMessage(e.InnerException, msg as IMethodCallMessage);
            }

            return new ReturnMessage(e, msg as IMethodCallMessage);
        }
    }
}

下面是你将如何使用它:

Here is how you would use it:

IMyInterface intf = LoggingProxy<IMyInterface>.Create(new MyClass());
intf.MyProcedure();

输出到控制台随后将是:

The output to console would then be:

调用之前:MyProcedure
你好世界维基 之后调用:MyProcedure

Before invoke: MyProcedure
Hello World
After invoke: MyProcedure

这篇关于动态创建一个代理类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆