我正在尝试动态创建一个代理类。我知道有一些非常好的框架可以做到这一点,但这纯粹是一个宠物项目,作为一种学习练习,所以我想自己做。
例如,如果我有以下实现接口(interface)的类:
interface IMyInterface
{
void MyProcedure();
}
class MyClass : IMyInterface
{
void MyProcedure()
{
Console.WriteLine("Hello World");
}
}
为了拦截此类的方法以便记录它们,我正在创建另一个类(我的代理类版本),它实现相同的接口(interface)但包含对“真实”类的引用。此类执行一个操作(例如日志记录),然后在真实类上调用相同的方法。
例如:
class ProxyClass : IMyInterface
{
private IMyInterface RealClass { get; set; }
void MyProcedure()
{
// Log the call
Console.WriteLine("Logging..");
// Call the 'real' method
RealClass.MyProcedure();
}
}
调用者然后改为调用代理类上的所有方法(我使用基本的自制 IoC 容器来注入(inject)代理类代替真实类)。我使用此方法是因为我希望能够在运行时将 RealClass
换成另一个实现相同接口(interface)的类。
有没有办法在运行时创建 ProxyClass
并填充其 RealClass
属性,以便它可以用作真实类的代理?有没有一种简单的方法可以做到这一点,或者我是否需要使用类似 Reflection.Emit
的东西来生成 MSIL?
最佳答案
看看System.Runtime.Remoting.Proxies.RealProxy .您可以使用它来创建一个从调用者的角度来看似乎是目标类型的实例。 RealProxy.Invoke 提供了一个点,您可以从中简单地调用基础类型上的目标方法或在调用之前/之后执行其他处理(例如日志记录)。
这是在每次方法调用之前/之后记录到控制台的代理示例:
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);
}
}
}
以下是您将如何使用它:
IMyInterface intf = LoggingProxy<IMyInterface>.Create(new MyClass());
intf.MyProcedure();
控制台的输出将是:
在调用之前:MyProcedure
Hello World
调用后:MyProcedure
关于c# - 动态创建代理类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15733900/