Castle DynamicProxy-创建涉及用作GTR的GTP的代理时失败
本文关键字:GTP 代理 失败 GTR 创建 DynamicProxy- Castle | 更新日期: 2023-09-27 18:23:47
好吧,现在我真的很困惑。
我最初有这个问题,根据海报,这是Castle.DynamicProxy版本的问题,它被ILMerged到最新的Rhino.Mocks库中。据几位权威人士称,它已经被修复在最新的城堡中,但该图书馆并没有将其打造成新的RhinoMocks。大多数人都说"只需下载Rhino源代码和最新的Castle,然后构建自己的版本"。
所以,我就是这么做的;我从Ayende的GitHub中获取了Rhino主干源的ZIP,打开并构建了它。然后,就像一个优秀的小TDDer一样,我创建了一个单元测试来确保我的更改有效(因为最新的Castle将DynamicProxy折叠到Core中,需要一些重要的引用更改):
[Test]
public void MockOfInterfaceMethodWithInterfaceGTR()
{
var mock = mocks.DynamicMock<ITestRestrictedInterface>();
Assert.NotNull(mock);
Expect.Call(mock.TestMethod(new Object2())).IgnoreArguments().Return(5);
mocks.ReplayAll();
Assert.AreEqual(5, mock.TestMethod(new Object2()));
}
...
internal interface ITestGenericInterface<TRest> where TRest:IObject1
{
int TestMethod<T>(T input) where T : TRest;
}
internal interface ITestRestrictedInterface:ITestGenericInterface<IObject2> { }
internal interface IObject1 { }
internal interface IObject2:IObject1 { }
internal class Object2:IObject2 { }
结果,当我用最新发布的Rhino在自己的生产代码中运行时?故障,显示以下消息:
System.TypeLoadException:类型上的方法"TestMethod"来自的"ITestRestrictedInterfaceProxy83ad369cdf41472c857f61561d434436"程序集"DynamicProxyGenAssembly2,版本=0.0.0.0,区域性=中性,PublicKeyToken=null试图隐式实现接口方法具有较弱的类型参数约束。
然而,当我在Rhino.Mocks.Tests项目中将此测试复制并粘贴到fixture中时,在不对引用库进行任何更改的情况下,测试通过。我对下载的源代码没有任何更改。我对测试方法和双方的相关接口/对象进行了零更改。我构建了一个新的Rhino.Mocks DLL(没有IL合并Castle库),并将它与Castle库复制回我的生产解决方案,重新运行测试,但它仍然失败,并返回相同的消息。
WTF?
我既不是Castle专家,也不是编译器大师,但我相信这个问题是RhinoMocks内部隐藏的一点魔法。测试程序集:
发件人https://github.com/ayende/rhino-mocks/blob/master/Rhino.Mocks.Tests/TestInfo.cs
using System.Runtime.CompilerServices;
using Rhino.Mocks;
[assembly: InternalsVisibleTo(RhinoMocks.StrongName)]
为了完整起见,RhinoMocks.StrongName被定义为:
/// <summary>
/// Used for [assembly: InternalsVisibleTo(RhinoMocks.StrongName)]
/// Used for [assembly: InternalsVisibleTo(RhinoMocks.NormalName)]
/// </summary>
public static class RhinoMocks
{
/// <summary>
/// Strong name for the Dynamic Proxy assemblies. Used for InternalsVisibleTo specification.
/// </summary>
public const string StrongName =
"DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7";
/// <summary>
/// Normal name for dynamic proxy assemblies. Used for InternalsVisibleTo specification.
/// </summary>
public const string NormalName = "DynamicProxyGenAssembly2";
/// <summary>
/// Logs all method calls for methods
/// </summary>
public static IExpectationLogger Logger = new NullLogger();
}
我在使用Moq时看到过类似的问题,Moq记录了这个问题。
问题是Castle中的DynamicProxy需要动态派生一个新类型,但没有可见性来查看程序集内部的接口。只需将InternalsVisibleTo添加到测试库的DynamicProxyGenAssembly2就可以解决这个问题。