68

OK、今私は本当に混乱しています。

私はもともとこの問題を抱えていました。これは、ポスターによると、最新の Rhino.Mocks ライブラリに ILMerged された 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、Version=0.0.0.0、Culture=neutral、PublicKeyToken=null' の型 'ITestRestrictedInterfaceProxy83ad369cdf41472c857f61561d434436' のメソッド 'TestMethod' は、より弱い型パラメーター制約を持つインターフェイス メソッドを暗黙的に実装しようとしました。

...しかし、このテストをコピーして Rhino.Mocks.Tests プロジェクトのフィクスチャに貼り付けると、参照されているライブラリに変更を加えずにテストが成功します。ダウンロードしたソースに変更を加えていません。テストメソッドと関連するインターフェイス/オブジェクトの両方にゼロの変更を加えました。新しい Rhino.Mocks DLL を作成し (Castle ライブラリを IL マージせずに)、それを Castle ライブラリと共に本番環境のソリューションにコピーし、テストを再実行しましたが、同じメッセージで失敗します。

なんてこと?

4

1 に答える 1

7

私は 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 を使用しているときに、同様の問題が発生しました。

問題は、Castle の DynamicProxy が新しい型を動的に派生させる必要があるが、アセンブリの内部にあるインターフェイスを表示する可視性がないことです。テスト ライブラリの DynamicProxyGenAssembly2 に InternalsVisibleTo を追加するだけで問題が解決するはずです。

于 2013-02-13T06:21:06.023 に答える