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


68

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

我最初遇到了这个问题,根据发布者的说法,这是ILMerges到最新Rhino.Mocks库中的Castle.DynamicProxy版本的问题。根据有关此问题的几个权威机构的说法,它已被固定在最新的Castle中,但该图书馆尚未将其改成新的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 { } 

结果如何与最新发布的Rhino以我自己的生产代码一起运行?失败,并显示以下消息:

System.TypeLoadException:来自程序集“ DynamicProxyGenAssembly2,版本= 0.0.0.0,区域性=中性,PublicKeyToken = null”中的类型“ ITestRestrictedInterfaceProxy83ad369cdf41472c857f61561d434436”上的方法“ TestMethod”尝试隐式实现类型参数约束较弱的接口方法。

...但是,当我将此测试复制并粘贴到Rhino.Mocks.Tests项目中的固定装置中时,无需对引用的库进行任何更改,则测试会通过。我对下载的源进行了零更改。我对测试方法和相关接口/对象都进行了零更改。我构建了一个新的Rhino.Mocks DLL(没有IL合并Castle库),并将其与Castle库一起复制回我的生产解决方案,重新运行测试,但仍然失败,并显示相同的消息。

WTF?


2
可能与此线程中确定的问题有关吗?stackoverflow.com/questions/6012420/…?也许它确实起作用的事实与该线程中指出的解决方法有关;也许您的模拟(通过某种方式)(而不是隐式地)在通过场景中实现了接口?
RJ Lohan 2012年

2
进行了一些谷歌搜索,发现该帖子说明了一个编译器错误。我不确定这是否适用于您的问题,但值得一看。他们在该职位上也有解决方案。
jduncanator

该错误似乎早已修复。
方舟

1
在他的最后一条信息中,我能感觉到发帖人的痛苦和痛苦:WTF?确实。
l46kok

Answers:


6

我既不是城堡专家,也不是编译专家,但我认为问题是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时,我也看到过类似的问题,该问题已记录在案

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


2
由于OP并未说出是否回答了他的问题,所以您会获得赏金,以表示愿意努力回答这个问题。
CloudyMarble
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.