定义动态代理的基类或基本功能(例如Castle,LinFu)

时间:2010-05-02 18:01:26

标签: c# proxy-classes

我在NHibernate forumns中问过这个问题,但我认为这更像是一个普遍的问题。 NHibernate使用代理生成器(例如Castle)来创建代理。

我想做的是扩展生成的代理,以便它实现我自己的一些自定义行为(即比较器)。我需要这个,因为以下标准的.NET行为无法产生正确的结果:

//object AC is a concrete class
collection.Contains(AC) = true

//object AP is a proxy with the SAME id and therefore represents the same instance as concrete AC
collection.Contains(AP) = false

如果我的比较器是由AP实现的(即执行id的匹配),那么collection.Contains(AP)将返回true,正如我所期望的那样,代理是隐式的。 (注意:对于那些说NH继承自你的基类的人,那么它确实如此,但NH也可以从接口继承 - 这就是我们正在做的事情)

我完全不确定这是可行的还是从哪里开始。这可以在NH使用的任何常见代理生成器中完成吗?

2 个答案:

答案 0 :(得分:2)

使用Castle DynamicProxy,你几乎没有选择。

首先是在创建代理时将IComparer<T>提供为additionalInterfacesToProxy之一。接口将没有实际的实现,因此您需要提供一个拦截器而不是调用Proceed将为方法提供实际的逻辑。

或者,您可以提供mixin,它实现所需的接口并提供您需要的逻辑。请注意,您很可能需要将mixin引用传递回代理或其目标。

仅适用于接口代理的第三个选项是设置基类proxyGenerationOptions.BaseClassForInterfaceProxy = typeof(SomethingImplementingComparer);

答案 1 :(得分:0)

LinFu.DynamicProxy可以实现这种行为,但是您必须将NHibernate提供的拦截器替换为您自己的自定义拦截器,该拦截器将其调用回原始拦截器:

var yourProxiedInterfaceInstance = ...

// Get the Interceptor that NHibernate uses

var proxy = (IProxy)yourProxiedInterfaceInstance;

var interceptor = proxy.Interceptor;

// You'll need to create a decorator class around the IInterceptor interface
var yourInterceptor = new SomeCustomInterceptor(interceptor); 

// Replace the interceptor here
proxy.Interceptor = yourInterceptor;

使用LinFu非常容易,因为它生成的每个代理实例都需要一个拦截器。如果更改拦截器,则可以自动更改代理的行为。我希望有所帮助。