Castle DynamicProxy - Fehler beim Erstellen eines Proxys mit einem als GTR verwendeten GTP


68

OK, jetzt bin ich wirklich verwirrt.

Ich hatte ursprünglich dieses Problem , das laut Postern ein Problem mit der Version von Castle.DynamicProxy ist, die ILMerged in die neueste Rhino.Mocks-Bibliothek enthält. Es wurde nach Angaben mehrerer Behörden zu diesem Thema im neuesten Schloss repariert, aber diese Bibliothek hat es nicht zu einem neuen Rhino.Mocks geschafft. Die meisten Leute sagen "Laden Sie einfach die Rhino-Quelle und das neueste Schloss herunter und erstellen Sie Ihre eigene Version".

Also habe ich genau das getan; Ich holte mir eine ZIP-Datei der Rhino-Trunk-Quelle aus Ayendes GitHub, öffnete sie und baute sie. Dann habe ich wie ein guter kleiner TDDer einen Komponententest erstellt, um sicherzustellen, dass meine Änderungen funktionieren (da das neueste Castle DynamicProxy in Core faltet und einige wichtige Referenzierungsänderungen erfordert):

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

Das Ergebnis, wenn in meinem eigenen Produktionscode mit dem neuesten veröffentlichten Rhino ausgeführt? Fehler mit der folgenden Meldung:

System.TypeLoadException: Die Methode 'TestMethod' für den Typ 'ITestRestrictedInterfaceProxy83ad369cdf41472c857f61561d434436' aus der Assembly 'DynamicProxyGenAssembly2, Version = 0.0.0.0, Culture = neutral, PublicKeyToken = null' hat versucht, eine Parameterbeschränkung implizit mit einer schwachen Parametermethode zu implementieren.

... Wenn ich diesen Test jedoch kopiere und in ein Fixture im Rhino.Mocks.Tests-Projekt einfüge, ohne Änderungen an den Bibliotheken vorzunehmen, auf die verwiesen wird, wird der Test bestanden. Ich habe keine Änderungen an der heruntergeladenen Quelle vorgenommen. Ich habe NULL Änderungen an der Testmethode und den zugehörigen Schnittstellen / Objekten auf beiden Seiten vorgenommen. Ich habe eine neue Rhino.Mocks-DLL erstellt (ohne die Castle-Bibliotheken IL-zusammenzuführen) und sie mit Castle-Bibliotheken zurück in meine Produktionslösung kopiert, den Test erneut ausgeführt und es schlägt immer noch mit derselben Meldung fehl.

WTF?


2
Könnte es mit dem in diesem Thread identifizierten Problem zusammenhängen? stackoverflow.com/questions/6012420/… ? Vielleicht hängt die Tatsache, dass es überhaupt funktioniert, mit der in diesem Thread angegebenen Problemumgehung zusammen. Vielleicht implementiert Ihr Mock (irgendwie) explizit (und nicht implizit) die Schnittstelle im Pass-Szenario?
RJ Lohan

2
Ein bisschen googeln hat diesen Beitrag aufgetaucht, der besagt, dass es sich um einen Compiler-Fehler handelt. Ich bin nicht sicher, ob dies auf Ihr Problem zutrifft, aber es ist einen Blick wert. Sie haben auch eine Lösung in diesem Beitrag.
jduncanator

Dieser Fehler scheint längst behoben zu sein.
Ark-Kun

1
Ich kann die Qual und den Schmerz des Plakats in seiner letzten Nachricht spüren: WTF? Tatsächlich.
l46kok

Antworten:


6

Ich bin kein Castle-Experte oder Compiler-Guru, aber ich glaube, das Problem ist ein bisschen Magie, die in der RhinoMocks.Tests-Assembly verborgen ist:

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

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

[assembly: InternalsVisibleTo(RhinoMocks.StrongName)]

Der Vollständigkeit halber ist RhinoMocks.StrongName definiert als:

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

Ich habe ein ähnliches Problem bei der Verwendung von Moq gesehen, bei dem dieses Problem dokumentiert ist .

Das Problem ist , dass Dynamic in Castle ableiten muss , um dynamisch einen neuen Typ , aber nicht über die Sichtbarkeit Ihrer Schnittstelle zu sehen , die ist intern auf Ihre Montage. Durch einfaches Hinzufügen von InternalsVisibleTo zur DynamicProxyGenAssembly2 zu Ihrer Testbibliothek sollte das Problem behoben werden.


2
Da das OP nicht gesagt hat, ob dies seine Frage beantwortet oder nicht, erhalten Sie die Prämie für die Bemühungen, dies zu beantworten.
CloudyMarble
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.