C# 如何在Castle DynamicProxy中处理受保护的通用重载?

C# 如何在Castle DynamicProxy中处理受保护的通用重载?,c#,generics,moq,castle,castle-dynamicproxy,C#,Generics,Moq,Castle,Castle Dynamicproxy,为具有重载方法签名的泛型对象创建Castle DynamicProxy时遇到了一个问题。我最初是通过Moq遇到这个问题的,但我能够通过手动生成一个相当简单的代理来重现相同的异常: using Castle.DynamicProxy; using NUnit.Framework; [TestFixture] public class TestOverloadedMethods { [Test] public void ProxyCreationFails() {

为具有重载方法签名的泛型对象创建Castle DynamicProxy时遇到了一个问题。我最初是通过Moq遇到这个问题的,但我能够通过手动生成一个相当简单的代理来重现相同的异常:

using Castle.DynamicProxy;
using NUnit.Framework;

[TestFixture]
public class TestOverloadedMethods
{
    [Test]
    public void ProxyCreationFails()
    {
        var generator = new ProxyGenerator();
        generator.CreateClassProxy(typeof(SomeDependency<SomeParam>),
            ProxyGenerationOptions.Default, new object[] { });
    }
}

public abstract class SomeDependency<T>
{
    protected virtual void Do(T param) { }
    public virtual void Do(SomeParam param) { }
}

public class SomeParam { }
以下黑客解决了该问题,但依赖于对类定义的更改:

  • 重命名其中一个方法,使它们不再重载
  • 对类中的代码重新排序,以便在受保护的方法之前定义公共方法

有没有一种方法可以在不修改依赖项代码的情况下创建代理?

我尝试直接使用Moq。当我执行
myMock.Setup(x=>x.do(Moq.It.IsAny())
时,根据C#重载解析规则,我似乎指向了我想要的
public
重载。如果我直接检查表达式树,
System.Linq.Expressions.expression expr=x=>x.Do(Moq.It.IsAny())
正文有一个
方法
(这是一个方法信息),其
IsPublic
为true。因此,对于C#表达式树,我指出了一个特定的重载,公共重载。所以Moq不能选择其他过载!从这个层次来看,这是一个bug。如果您试图用C#手工编写模拟,那么您的类
SomeDependency
也会出现问题。如果执行
类C:SomeDependency{}
,则即使两个重载合并(获取相同的签名),一切仍然正常。参数不来自
T
的重载似乎是首选。但是,只要您尝试
public override void Do(SomeParam param){}
protected override void Do(SomeParam param){}
,就会出现以下错误:错误CS0462:继承成员的SomeDependency.Do(SomeParam)和SomeDependency.Do(T)具有相同的签名…感谢您注意到这一点!SomeDependency的创建者只是将这些方法虚拟化,以便在单元测试期间对它们进行操作。因为在现实生活中从未有过覆盖,所以它是否可以被视为无效并不明显。我将要求依赖项生成器解决这个问题。可能是运行时/CLI无法在CIL字节码中指定当两个方法像这样联合时将覆盖哪个方法。如果是这种情况,Castle DynamicProxy中的“bug”永远无法修复,除非以某种方式消除.NET的限制。注意:即使
SomeDependency
中的两个重载中只有一个标记为
virtual
,而另一个为非virtual,也会出现问题。
System.TypeLoadException : Derived method 'Do' in type 'Castle.Proxies.SomeDependency`1Proxy' 
from assembly 'DynamicProxyGenAssembly2' cannot reduce access.

   at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type)
   at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
   at System.Reflection.Emit.TypeBuilder.CreateTypeInfo()
   at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.CreateType(TypeBuilder type)
   at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()
   at Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateType(String name, Type[] interfaces, INamingScope namingScope)
   at Castle.DynamicProxy.Generators.BaseProxyGenerator.ObtainProxyType(CacheKey cacheKey, Func`3 factory)
   at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
   at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
   at TestAmbiguousMethods.ProxyCreationFails() in TestOverloadedMethods.cs:line 11