2012-02-08 4 views
68

이제는 정말 혼란 스럽습니다.캐슬 DynamicProxy - GTR로 사용되는 GTP와 관련된 프록시를 만들 때 오류가 발생했습니다.

원래는 this problem이었습니다. 포스터에 따르면 최신 Rhino.Mocks 라이브러리에 ILMerged 된 Castle.DynamicProxy 버전의 문제가 있습니다. 이 주제에 관한 몇몇 권위에 따르면, 최신 성에서 수정되었지만, 그 라이브러리는 새로운 Rhino로 만들지 않았습니다. 모의. 대부분의 사람들은 "Rhino 소스와 최신 성을 다운로드하고 자신 만의 버전을 구축하십시오"라고 말하고 있습니다.

그래서, 정확하게 그랬습니다. Ayende의 GitHub에서 Rhino 트렁크 소스의 ZIP을 가져 와서 열었습니다. 그런 다음, 좋은 작은 TDD 실천가처럼, 나는 (성 몇 가지 중요한 참조 변경 요구, 코어에 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은, 문화 = 중립, PublicKeyToken = null이'암시하려 매개 변수 제약이 약한 유형의 인터페이스 메소드 을 구현하십시오.

... 그러나 참조 된 라이브러리를 변경하지 않고이 테스트를 복사하여 Rhino.Mocks.Tests 프로젝트의 픽스처에 붙여 넣으면 테스트가 통과합니다. 다운로드 한 소스를 전혀 변경하지 않았습니다. 테스트 메소드와 관련된 인터페이스/객체를 양쪽에서 ZERO 변경했습니다. 나는 새로운 Rhino.Mocks DLL을 만들었고 (IL-Merge하지 않고 Castle libs) 캐슬 라이브러리로 복사하여 다시 내 프로덕션 솔루션에 복사하고 테스트를 다시 실행했지만 여전히 동일한 메시지가 나타나지 않습니다.

WTF?

+2

이 스레드에서 확인 된 문제와 관련이있을 수 있습니다. http://stackoverflow.com/questions/6012420/why-does-this-generics-scenario-cause-a-typeloadexception? 아마도 그것이 실제로 작동한다는 사실은 그 스레드에서 언급 된 해결 방법과 관련이있을 것입니다. 어쩌면 당신의 모의가 패스 시나리오에서 인터페이스를 명시 적으로 (암시 적으로가 아니라) 명시 적으로 (어떻게 든) 명시 적으로 구현할 것인가? –

+2

약간의 인터넷 검색 결과가이 [게시물] (http : // platinumdogs.me/2010/04/09/c-implementing-generic-method-of-generic-interface-causes-runtime-exception /)에 나와 있습니다. 이 문제가 귀하의 문제에 적용되는지는 잘 모르겠지만 그 가치가 있습니다. 그들은 또한 해당 게시물에 대한 해결책을 가지고 있습니다. – jduncanator

+0

그 버그는 오래 전에 수정 된 것 같습니다. –

답변

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)] 

그리고에서 MOQ, which has this issue documented을 사용할 때 비슷한 문제를 본 적이

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

:로 완전성을 위해, RhinoMocks.StrongName가 정의됩니다.

캐슬의 DynamicProxy는 새로운 유형을 동적으로 생성해야하지만 사용자의 인터페이스를 볼 수있는 가시성이 없으므로 어셈블리에 내부입니다. 테스트 라이브러리에 DynamicProxyGenAssembly2에 InternalsVisibleTo를 추가하기 만하면 문제가 해결됩니다.

+1

OP가 질문에 답하는 지 말하지 않았기 때문에 답을하기위한 노력을 보여주는 바운티를 얻습니다. – CloudyMarble