如何动态修饰类
本文关键字:动态 何动态 | 更新日期: 2023-09-27 17:55:22
我有一个简单的装饰器类,如下所示。 请注意,我的公共方法都是如何创建要修饰的类的新实例,然后将调用转发到该实例。
这个类的问题在于,每当IMyService
更新时,我也必须更新这个代理类。
public class MyProxyService : IMyService
{
readonly IMyServiceFactory _realServiceFactory;
public MyProxyService(IMyServiceFactory realServiceFactory)
{
_realServiceFactory = realServiceFactory;
}
private IMyService CreateRealService()
{
return _realServiceFactory.CreateRealService();
}
public int A()
{
return CreateRealService().A();
}
public int B(int b1)
{
return CreateRealService().B(int b1);
}
public int C(int c1, int c2)
{
return CreateRealService().C(c1,c2);
}
public int D(int d1, int d2, int d3)
{
return CreateRealService().D(d1,d2,d3);
}
public void E()
{
CreateRealService().E();
}
}
我尝试使用 Castle.DynamicProxy
创建一个动态版本,到目前为止没有任何运气。
有人知道一种好的、简单的方法来动态创建这样的装饰器吗?
我能够使用DynamicProxy.ProxyGenerator
的CreateInterfaceProxyWithTargetInterface(..)来工作。
我首先创建了一个动态代理工厂。 这将返回一个代理对象,每个方法将被提供的IInterceptor
截获:
public class MyDynamicallyDecoratedServiceClientFactory
{
readonly ProxyGenerator _proxyGenerator;
readonly IInterceptor _interceptor;
public MyServiceClientFactory(IInterceptor interceptor)
{
_interceptor = interceptor;
_proxyGenerator = new ProxyGenerator();
}
public IMyService Create()
{
IMyService proxy = _proxyGenerator.CreateInterfaceProxyWithTargetInterface<IMyService>(null, _interceptor);
return proxy;
}
}
然后我实现了拦截器。 每次方法调用时,都会调用此拦截器,它将从提供的IMyServiceFactory
创建一个新IMyService
,并将方法调用委托给该新实例。
public class MyServiceClientInterceptor : IInterceptor
{
readonly IMyServiceFactory _svcFactory;
public MyServiceClientInterceptor(IMyServiceFactory svcFactory)
{
_svcFactory = svcFactory;
}
public void Intercept(IInvocation invocation)
{
IMyService realService = _svcFactory.Create();
IChangeProxyTarget changeProxyTarget = invocation as IChangeProxyTarget;
changeProxyTarget.ChangeInvocationTarget(realService);
invocation.Proceed();
}
}
最后,要利用所有这些:
// Create a service factory (the to-be-decorated class)
IMyServiceFactory myRealServiceFactory = /* ... */;
// Create a factory that will create decorated services
MyServiceClientInterceptor interceptor =
new MyServiceClientInterceptor(myRealServiceFactory);
MyDynamicallyDecoratedServiceClientFactory svcFactory =
new MyDynamicallyDecoratedServiceClientFactory(interceptor);
// Create a service client
IMyService svc = svcFactory.Create();
// Use it!
svcProxy.A();