Castle DynamicProxy – 创build代理涉及用作GTR的GTP时失败

好的,现在我真的很困惑。

我原本就有这个问题 ,根据海报,Castle.DynamicProxy的版本被ILMerged到最新的Rhino.Mocks库中。 根据这个问题,有几个权威人士已经在最新的城堡里定下了这个图书馆,但是这个图书馆并没有把它变成一个新的犀牛。 大多数人都在说“只要下载Rhino源码和最新的Castle,build立你自己的版本”。

所以,我就是这么做的。 我从Ayende的GitHub抓取了犀牛干货源的一个ZIP,打开它,然后build立它。 然后,就像一个很好的TDDer,我创build了一个unit testing,以确保我的更改能够正常工作(因为最新的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 { } 

结果,当我在最新发布的犀牛自己的生产代码运行? 失败并显示以下消息:

System.TypeLoadException:来自程序集“DynamicProxyGenAssembly2,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null”的types为“ITestRestrictedInterfaceProxy83ad369cdf41472c857f61561d434436”的方法“TestMethod”尝试隐式实现具有较弱types参数约束的接口方法。

…但是,当我将这个testing复制并粘贴到Rhino.Mocks.Tests项目的一个fixture中,而不对引用的库进行任何更改时,testingPASSES。 我已经对下载的源文件进行了零改变。 我已经对testing方法和相关接口/对象进行了ZERO更改。 我构build了一个新的Rhino.Mocks DLL(没有IL合并Castle库),并将其与Castle libs一起复制回我的生产解决scheme,重新运行testing,并且仍然失败并显示相同的消息。

WTF?

我不是一个城堡专家,也不是编译器大师,但是我相信这个问题有点隐藏在RhinoMocks.Tests程序集中:

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时,我遇到了类似的问题, 这个问题已经被logging 。

问题是Castle中的DynamicProxy需要dynamic地派生一个新types,但是没有可见性来查看你的接口,这个接口在你的程序集内部 。 只需将InternalsVisibleTo添加到您的testing库的DynamicProxyGenAssembly2即可解决问题。