68 votes

Château DynamicProxy - échec lors de la création de proxy impliquant un GTP utilisée comme un GTR

OK, maintenant, je suis vraiment confus.

J'ai d'abord eu ce problème, qui est, selon les affiches, un problème avec la version de Château.DynamicProxy c'est ILMerged dans les derniers Rhinocéros.On se moque de la bibliothèque. Il a, selon plusieurs autorités sur le sujet, été corrigé dans la dernière Château, mais que la bibliothèque n'a pas fait dans un nouveau Rhino.Des simulacres. La plupart des gens disent "il suffit de télécharger le Rhino source et le dernier Château et construire votre propre version".

Donc, j'ai fait exactement cela; j'ai attrapé un ZIP de la Rhino tronc source de Ayende de GitHub, il s'est ouvert, et l'a construit. Puis, comme un bon petit TDDer, j'ai créé une unité de test pour s'assurer que mes changements travaillé (parce que la dernière Château plis DynamicProxy de Base, nécessitant d'importants référencement de modifications):

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

Le résultat, lorsque vous exécutez dans mon propre code de production avec la dernière version de Rhino? L'échec avec le message suivant:

Système.TypeLoadException : la Méthode 'TestMethod" sur le type 'ITestRestrictedInterfaceProxy83ad369cdf41472c857f61561d434436" de l'assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' a tenté implicitement de mettre en œuvre une méthode d'interface avec moins de contraintes de paramètre de type.

...Cependant, lorsque je fais un copier-coller de ce test dans un appareil de Rhino.Des simulacres.Les Tests du projet, sans aucune modification de référencé les bibliothèques, le test PASSE. J'ai fait aucun changement à la source téléchargé. J'ai fait aucun changement à la méthode d'essai et interfaces/objets sur les deux côtés. J'ai construit un nouveau Rhino.On se moque de DLL (sans IL-la fusion du Château libs) et copié avec le Château de libs de retour à ma solution de production, re-couru à l'essai, et il échoue toujours avec le même message.

WTF?

6voto

bryanbcook Points 7184

Je ne suis pas un Château expert ni compilateur gourou, mais je crois que la question est un peu de la magie qui est caché à l'intérieur de la RhinoMocks.Les Tests de l'assemblée:

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

using System.Runtime.CompilerServices;
using Rhino.Mocks;

[assembly: InternalsVisibleTo(RhinoMocks.StrongName)]

Et par souci d'exhaustivité, RhinoMocks.StrongName est défini comme:

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

J'ai vu un problème similaire lors de l'utilisation de Moq, qui a ce problème documenté.

Le problème est que DynamicProxy dans le Château besoins dynamiquement pour obtenir un nouveau type, mais n'a pas de visibilité pour voir votre interface qui est interne à votre assemblée. Simplement en ajoutant de l'InternalsVisibleTo à la DynamicProxyGenAssembly2 à votre bibliothèque de test devrait résoudre le problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X