城堡DynamicProxy:进行代理的接口时,如何代理等于? [英] Castle DynamicProxy : How to Proxy Equals when proxying an interface?

查看:151
本文介绍了城堡DynamicProxy:进行代理的接口时,如何代理等于?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用城堡DynamicProxy代理接口,提供它的一个实例ProxyGenerator.CreateInterfaceProxyWithTarget。我还需要确保调用的Equals,GetHash code和toString击中的具体实例的方法,我想过去,我不能得到那个工作。

I need to use Castle DynamicProxy to proxy an interface by providing an instance of it to ProxyGenerator.CreateInterfaceProxyWithTarget. I also need to make sure that calls to Equals, GetHashCode and ToString hits the methods on the concrete instance, that I am passing, and I can't get that to work.

在换句话说,我想这个小样本打印两次,而实际上它打印真,假

In other words, I'd like this small sample to print True twice, while in fact it prints 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);
    }
}

这可能与DynamicProxy?怎么样?

Is this possible with DynamicProxy ? How ?

推荐答案

这是一个有点棘手。 <一href="http://stw.castleproject.org/Tools.DynamicProxy-Introduction.ashx#Interception_pipeline_5">Take看看文档的代理是如何工作的。接口代理包装一个对象,并拦截调用指定的接口(S)。由于等于是不是该接口的第二个呼叫到等于在比较代理的一部分,而不是他们的目标。

This is a bit tricky. Take a look at documentation on how proxies work. Interface proxies wrap an object and intercept calls to designated interface(s). Since Equals is not part of that interface the second call to equals is comparing proxies, not their targets.

那么,什么提供了实现第二个等于打电话?

So what provides the implementation for the second Equals call?

代理只是另一个类实现你的 IDummy 接口。正如任何类它也有一个基类,而这对基实现等于被调用的。这个基类是默认的 System.Object的

Proxy is just another class implementing your IDummy interface. As any class it also has a base class, and that's the base implementation of Equals that gets invoked. This base class is by default System.Object

我希望你现在看到这是怎么回事。解决这一问题的办法是告诉代理实现,将转发呼叫代理目标有些代理知道基类。其实现的一部分可能是这样的:

I hope you see now where this is going. Solution to this problem is to tell proxy to implement some proxy aware base class that will forward the calls to proxy target. Part of its implementation might look like this:

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
}

现在你只需要,而不是默认的指示代理生成器使用这个基类的接口代理。

Now you only need to instruct the proxy generator to use this base class for your interface proxies, instead of the default.

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

这篇关于城堡DynamicProxy:进行代理的接口时,如何代理等于?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆