Castle DynamicProxy:如何在代理接口时代理等于?

dri*_*iis 10 .net c# castle castle-dynamicproxy

我需要使用Castle DynamicProxy通过向ProxyGenerator.CreateInterfaceProxyWithTarget提供它的实例来代理接口.我还需要确保调用Equals,GetHashCode和ToString命中具体实例上的方法,我正在传递,而我无法使其工作.

换句话说,我想要这个小样本打印True两次,而实际上它打印True,False:

using System;
using Castle.Core.Interceptor;
using Castle.DynamicProxy;

public interface IDummy
{
    string Name { get; set; }
}

class Dummy : IDummy
{
    public string Name { get; set; }

    public bool Equals(IDummy other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Equals(other.Name, Name);
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as IDummy);
    }      
}

class Program
{
    static void Main(string[] args)
    {
        var g = new ProxyGenerator();
        IDummy first = new Dummy() {Name = "Name"};
        IDummy second = new Dummy() {Name = "Name"};
        IDummy firstProxy = g.CreateInterfaceProxyWithTarget(first, new ConsoleLoggerInterceptor());
        IDummy secondProxy = g.CreateInterfaceProxyWithTarget(second, new ConsoleLoggerInterceptor());

        Console.WriteLine(first.Equals(second));         
        Console.WriteLine(firstProxy.Equals(secondProxy));
    }
}

internal class ConsoleLoggerInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("Invoked " + invocation.Method.Name);
    }
}
Run Code Online (Sandbox Code Playgroud)

DynamicProxy可以实现吗?怎么样 ?

Krz*_*mic 12

这有点棘手.看一下代理如何工作的文档.接口代理包装对象并拦截对指定接口的调用.由于Equals不是该接口的一部分,因此对equals的第二次调用是比较代理,而不是它们的目标.

那么是什么提供了第二次Equals调用的实现?

代理只是实现您的IDummy界面的另一个类.与任何类一样,它也有一个基类,这是它的基本实现Equals被调用.默认情况下,此基类System.Object

我希望你现在看到它的发展方向.解决此问题的方法是告诉代理实现一些代理感知基类,该基类将调用转发给代理目标.部分实现可能如下所示:

public class ProxyBase
{
    public override bool Equals(object obj)
    {
        var proxy = this as IProxyTargetAccessor;
        if (proxy == null)
        {
            return base.Equals(obj);
        }
        var target = proxy.DynProxyGetTarget();
        if (target == null)
        {
            return base.Equals(obj);
        }
        return target.Equals(obj);
    }
    // same for GetHashCode
}
Run Code Online (Sandbox Code Playgroud)

现在,您只需要指示代理生成器将此基类用于接口代理,而不是默认值.

var o = new ProxyGenerationOptions();
o.BaseTypeForInterfaceProxy = typeof(ProxyBase);
IDummy firstProxy = g.CreateInterfaceProxyWithTarget(first, o);
IDummy secondProxy = g.CreateInterfaceProxyWithTarget(second, o);
Run Code Online (Sandbox Code Playgroud)