如何动态修饰类

本文关键字:动态 何动态 | 更新日期: 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();