Castle DynamicProxy - 创建涉及用作GTR的GTP的代理时失败

Kei*_*thS 68 c# rhino-mocks castle-dynamicproxy rhino-commons

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

我最初遇到这个问题,根据海报,问题是Castle.DynamicProxy的版本是ILMerged到最新的Rhino.Mocks库.据该主题的一些权威人士称,它已经在最新的城堡中得到了修复,但该库还没有成为新的Rhino.Mocks.大多数人都说"只需下载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 { } 
Run Code Online (Sandbox Code Playgroud)

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

System.TypeLoadException:来自程序集'DynamicProxyGenAssembly2,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null'的类型'ITestRestrictedInterfaceProxy83ad369cdf41472c857f61561d434436'上的方法'TestMethod'试图隐式地实现具有较弱类型参数约束的接口方法.

...但是,当我将此测试复制并粘贴到Rhino.Mocks.Tests项目中的fixture中时,不对引用的库进行任何更改,测试PASSES.我对下载的源进行了零更改.我对两侧的测试方法和相关接口/对象进行了ZERO更改.我构建了一个新的Rhino.Mocks DLL(没有IL合并Castle libs)并将它与Castle libs一起复制回我的生产解决方案,重新运行测试,它仍然失败并显示相同的消息.

WTF?

bry*_*ook 6

我不是Castle专家也不是编译器大师,但我相信这个问题有点神奇,隐藏在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)]
Run Code Online (Sandbox Code Playgroud)

为了完整起见,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();
}
Run Code Online (Sandbox Code Playgroud)

我在使用Moq时遇到了类似的问题,Moq 记录了这个问题.

问题是Castle中的DynamicProxy需要动态派生一个新类型,但是没有可见性来查看程序集内部的接口.只需将InternalsVisibleTo添加到DynamicProxyGenAssembly2到测试库就可以解决问题.

  • 由于OP并未说出是否回答了他的问题,所以您会获得赏金,以表示愿意回答这个问题。 (2认同)