我有一个简单的装饰类,如下所示。注意我的公共方法如何创建一个待装饰类的新实例,然后将调用转发给该实例。
这个类的问题是每当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
创建动态版本,到目前为止没有任何运气。
任何人都知道动态创建这样的装饰器的好方法吗?
答案 0 :(得分:4)
我能够使用DynamicProxy.ProxyGenerator
的{{3}}让这个工作正常。
我首先创建了一个动态代理工厂。这将返回一个代理对象,每个方法都将被提供的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;
}
}
然后我实现了拦截器。在每个方法调用时,将调用此拦截器,它将从提供的IMyService
创建一个新的IMyServiceFactory
,并将方法调用委托给该新实例。
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();