c# rhino-mocks castle-dynamicproxy rhino-commons

c# - Castle DynamicProxy-Fallo al crear un proxy que involucra un GTP utilizado como GTR



rhino-mocks castle-dynamicproxy (1)

No soy un experto en Castle ni compilador, pero creo que el problema es un poco de magia que está oculta dentro del ensamblado de RhinoMocks.Tests:

Desde https://github.com/ayende/rhino-mocks/blob/master/Rhino.Mocks.Tests/TestInfo.cs

using System.Runtime.CompilerServices; using Rhino.Mocks; [assembly: InternalsVisibleTo(RhinoMocks.StrongName)]

Y para completar, RhinoMocks.StrongName se define como:

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

He visto un problema similar al usar Moq, que tiene este problema documentado .

El problema es que DynamicProxy en Castle necesita derivar dinámicamente un nuevo tipo pero no tiene visibilidad para ver su interfaz que es interna para su ensamblado. Simplemente agregando el InternalsVisibleTo al DynamicProxyGenAssembly2 a su biblioteca de prueba debería resolver el problema.

OK, ahora estoy realmente confundido.

Originalmente tuve este problema , que según los carteles, es un problema con la versión de Castle.DynamicProxy que está ILMerged en la última biblioteca de Rhino.Mocks. Según varias autoridades sobre el tema, se ha corregido en el último castillo, pero esa biblioteca no se ha convertido en un nuevo Rhino.Mocks. La mayoría de la gente dice "simplemente descargue la fuente de Rhino y la última versión de Castle y cree su propia versión".

Entonces, hice exactamente eso; Agarré un ZIP de la fuente de troncos de Rhino del GitHub de Ayende, lo abrí y lo construí. Luego, como un buen pequeño TDDer, creé una prueba unitaria para asegurarme de que mis cambios funcionaban (porque el último Castle dobla DynamicProxy en Core, lo que requiere algunos cambios de referencia significativos):

[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 { }

El resultado, cuando se ejecuta en mi propio código de producción con el último lanzamiento de Rhino? Fracaso con el siguiente mensaje:

System.TypeLoadException: Método ''TestMethod'' en el tipo ''ITestRestrictedInterfaceProxy83ad369cdf41472c857f61561d434436'' del ensamblado ''DynamicProxyGenAssembly2, Version = 0.0.0.0, Culture = neutral, PublicKeyToken = null'' intentó implementar implícitamente un método de interfaz con restricciones de parámetros de tipo más débil.

... Sin embargo, cuando copio y pego esta prueba en un dispositivo en el proyecto Rhino.Mocks.Tests, sin realizar ningún cambio en las bibliotecas a las que se hace referencia, la prueba PASSES. He realizado cero cambios en la fuente descargada. Realicé CERO cambios en el método de prueba y las interfaces / objetos relacionados en ambos lados. Construí una nueva DLL de Rhino.Mocks (sin IL-fusionar las bibliotecas de Castle) y la copié con Castle libs en mi solución de producción, volví a ejecutar la prueba y aún falla con el mismo mensaje.

WTF?