【问题标题】:Castle DynamicProxy - Failure when creating proxy involving a GTP used as a GTRCastle DynamicProxy - 创建涉及用作 GTR 的 GTP 的代理时失败
【发布时间】:2012-02-29 11:04:12
【问题描述】:

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

我最初有this problem,根据海报,这是 ILM 合并到最新 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:类型上的方法“TestMethod” 'ITestRestrictedInterfaceProxy83ad369cdf41472c857f61561d434436'来自 程序集'DynamicProxyGenAssembly2,版本=0.0.0.0,文化=中性, PublicKeyToken=null' 试图隐式实现一个接口方法 具有较弱的类型参数约束。

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

WTF?

【问题讨论】:

  • 可能与此线程中确定的问题有关吗? stackoverflow.com/questions/6012420/… ?也许它完全起作用的事实与该线程中提到的解决方法有关;也许您的模拟是(以某种方式)显式(而不是隐式)实现传递场景中的接口?
  • 一点点谷歌搜索发现了这个post,它说明它是一个编译器错误。我不确定这是否适用于您的问题,但值得一看。他们在那篇文章中也有解决方案。
  • 那个bug好像早就修复了。
  • 在发帖人的最后一条信息中我能感受到发帖者的痛苦和痛苦:WTF?确实。

标签: c# rhino-mocks castle-dynamicproxy rhino-commons


【解决方案1】:

我不是 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)]

为了完整起见,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 时遇到了类似的问题,which has this issue documented

问题在于 Castle 中的 DynamicProxy 需要动态派生新类型,但无法查看您的程序集内部的界面。只需将 InternalsVisibleTo 添加到 DynamicProxyGenAssembly2 到您的测试库即可解决问题。

【讨论】:

  • 由于 OP 没有说这是否回答了他的问题,所以你会因为努力回答这个问题而获得赏金。
猜你喜欢
  • 1970-01-01
  • 2012-06-20
  • 1970-01-01
  • 1970-01-01
  • 2012-04-10
  • 2011-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多