2012-02-08 55 views
68

好吧,現在我真的很困惑。Castle DynamicProxy - 創建涉及GTP的代理失敗時用作GTR

我原本有this problem,根據海報,Castle.DynamicProxy的版本被ILMerged加入到最新的Rhino.Mocks庫中。根據有關這方面的幾個權威機構,它已經在最新的城堡中得到修復,但該圖書館並沒有將它變成新的Rhino.Mocks。大多數人都在說「只需下載Rhino源代碼和最新的Castle並構建您自己的版本」。

所以,我就是這麼做的;我從Ayende的GitHub抓取了犀牛幹線源的ZIP,打開它並構建它。然後,像一個很好的小TDDer,我創建了一個單元測試,以確保我的變化工作(因爲最新的城堡摺疊DynamicProxy爲核心,需要一些顯著引用變化):

[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,文化=中性, 公鑰=空' 試圖隱式用較弱的類型參數約束實現接口方法 。

...但是,當我在Rhino.Mocks.Tests項目中將此測試複製並粘貼到夾具中時,未對引用的庫進行任何更改,則測試PASSES。我已對下載的源進行了零更改。我已經對測試方法和相關接口/對象進行了ZERO更改。我構建了一個新的Rhino.Mocks DLL(沒有IL合併Castle庫),並將它與Castle libs一起復制回我的生產解決方案,重新運行測試,並且仍然失敗並顯示相同的消息。

WTF?

+2

它可能與此線程中標識的問題有關; http://stackoverflow.com/questions/6012420/why-does-this-generics-scenario-cause-a-typeloadexception?也許它正在工作的事實與該線程中提到的解決方法有關;也許你的模擬(在某種程度上)明確地(而不是隱式地)在通過場景中實現接口? – 2012-11-19 03:14:48

+2

有一點谷歌搜索出現了這個[post](http:// platinumdogs。me/2010/04/09/c-implementation-generic-method-of-generic-interface-causes-runtime-exception /),它說明了它的編譯器錯誤。我不確定這是否適用於您的問題,但值得一看。他們在這篇文章中也有解決方案。 – jduncanator 2013-01-09 03:37:18

+0

這個錯誤似乎很久以前就已經修復了。 – 2013-02-10 20:45:33

回答

4

我不是一個城堡的專家,也沒有編譯器大師,但我相信這個問題是一個神奇的一點是隱藏的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)] 

而且

/// <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(); 
} 

我使用起訂量,which has this issue documented當看到一個類似的問題:爲了完整起見,如,RhinoMocks.StrongName定義。

問題是Castle中的DynamicProxy需要動態派生一個新類型,但是沒有可見性來查看您的接口,它是內部到您的程序集。只需將InternalsVisibleTo添加到您的測試庫的DynamicProxyGenAssembly2即可解決問題。

+1

由於OP沒有說這是否回答他的問題,所以你得到賞金表示努力回答這個問題。 – CloudyMarble 2013-02-14 12:42:00