Typ existiert in 2 Baugruppen

74

Ich habe zwei .NET Interop-Assemblys aus zwei verschiedenen COM-DLLs von Drittanbietern erstellt. Beide COM-DLLs enthielten einen Typ namens COMMONTYPE. Daher COMMONTYPEwird jetzt auch durch die beiden Interop-Baugruppen belichtet.

Ich habe ein drittes Projekt, das diese beiden Interop-Assemblys verwenden muss, und ich erhalte den berüchtigten Fehler bei der Kompilierungszeit:

Der Typ <ABC>existiert in <ASSEMBLY1.dll>und<ASSEMBLY2.dll>

Da die COM-DLLs von einem Drittanbieter bereitgestellt werden, habe ich keinen Zugriff auf den Quellcode und schreibe eine C # -Konsolenanwendung. Dies bedeutet, dass ich keine web.config-Datei habe, in der ich die Problemumgehung hinzufügen könnte debug=false. Was kann ich tun?

Kou S Hal
quelle
Ich bin hierher gekommen, weil Visual Studio sich über den Typ beschwert hat, den JsonConvert sowohl in Newtonsoft.Json.Torq als auch in Newtonsoft.Json gibt
Matthew

Antworten:

164

Ich weiß, dass dies alt ist, aber es gibt einen einfacheren Weg als den aufgeführten. Dies funktioniert, wenn Sie auf zwei Assemblys verweisen , die Typen mit genau demselben Namen und Namespace gemeinsam nutzen.

Wenn Sie mit der rechten Maustaste auf den Verweis auf Ihre DLL klicken und Eigenschaften auswählen, sehen Sie, dass hier eine Eigenschaft namens "Aliase" ist.

Geben Sie hier die Bildbeschreibung ein

Der Standardwert ist "global" . Ändern Sie dies für eine der in Konflikt stehenden Assemblys in einen anderen Wert. Im folgenden Beispiel habe ich es von "global" in "Ziel" geändert.

Als Nächstes müssen Sie in Ihrer Codedatei das Schlüsselwort extern verwenden , um diesen Alias ​​als Namespace auf Stammebene für diese Typen zu verwenden. In diesem Beispiel würden Sie Folgendes oben in Ihre CS-Datei einfügen:

extern alias destination

In dieser Datei können Sie nun auf beide Typen verweisen.

extern alias destination;
namespace Test
{
    public static class TestClass
    {
        public static void Success()
        {
            var foo = destination::Some.Duplicate.Namespace.SomeDuplicateType();
            var bar = Some.Duplicate.Namespace.SomeDuplicateType();
        }
    }
}
Tom
quelle
1
Schätzen Sie die viel bessere Antwort! Dies ist offensichtlich, wofür Aliase im Grunde genommen sind
PandaWood
4
Für mich auch definitiv die beste Antwort. Andere Lösungen würden nicht einmal funktionieren, da ich zwei genau gleiche DLLs habe, eine wird nur mit ILMerge in einer anderen zusammengeführt. Problem gelöst
Johnny
Ich möchte hier eine Frage von @bunkerdive erneut stellen (die beliebteste Antwort): Wie funktioniert das mit NuGet-Paketen? Wenn Sie versuchen, den Alias ​​VS zu ändern, erhalten Sie einen Fehler: Ein ausgewertetes Objekt, das aus einer importierten Datei stammt, kann nicht geändert werden
Geordie
1
Ich ging auf Referenzen ein, wählte das von Nuget installierte Paket aus und setzte dann den Alias ​​auf Ziel. Arbeitete wie ein Zauber ...
Zonus
1
@PedroGaspar liegt möglicherweise daran, dass Sie Visual Studio "Community" verwenden. Ich bin auf VS2017 Enterprise und habe dies erst vor 5 Sekunden implementiert. Einige niedrigere Versionen von VS bieten keine gute Unterstützung für Unit-Tests.
AlbatrossCafe
13

Sofern die Namespaces der Anbieter nicht identisch sind (unwahrscheinlich), sind die Typdefinitionen zu diesem Zeitpunkt tatsächlich getrennt. Was Sie tun müssen (und dies ist manchmal eine vollständige PITA), ist, einen Namespace-Alias ​​in Ihrer using-Anweisung zu erstellen, anstatt einfach die Anweisung carte blanche anzuwenden. Auf diese Weise können Sie die Namespaces neu identifizieren:

using Vendor1 = Vendor.Namespace;
using Vendor2 = OtherVendor.Namespace;

...

Vendor1.COMMONTYPE blah = new Vendor1.COMMONTYPE();
Vendor2.COMMONTYPE blah2 = new Vendor2.COMMONTYPE();

Dies bedeutet, dass für diese Anbieter der spezifische Alias ​​für alle Typen in jedem Namespace verwendet wird.

Joel Etherton
quelle
Dies würde mir sicherlich helfen, die Fehler bei der Kompilierung zu beheben. Aber kann ich nichts tun, damit .NET beim Erstellen einer Assembly bestimmte Typen ignoriert, sodass ich nur in einer der Assemblys den gemeinsamen Typ habe?
Kou S Hal
1
@KouSHal: Die einzige Möglichkeit, dies zu tun, besteht darin, eine Wrapper-Klasse zu erstellen, die auf eine der Herstellerbibliotheken verweist und alle Klassen, Erweiterungsmethoden usw. als Proxy verfügbar macht. Wenn es sich um eine kleine Bibliothek mit nur wenigen Klassen handelt, wäre dies nicht allzu schwierig, aber wenn es sich um die meisten Anbieterbibliotheken handelt, wäre dies ein Albtraum, den es zu erstellen und noch schlimmer zu warten gilt.
Joel Etherton
13

Alte Frage, aber eine einfachere Option gefunden ... Wählen Sie die Referenz aus, die Sie verwenden möchten ... Ändern Sie unter Eigenschaften die Aliase in 'xyz'. Jetzt in der Codezeile oben hinzufügen:

extern alias xyz;

Fügen Sie dann Folgendes hinzu:

using xyz.VENDOR2.Type;

oder eine andere Art der Verwendung mit:

using OtherNameSpace = xyz.VENDOR2.Type;

Jetzt sollten Sie in der Lage sein, die Referenz wie folgt explizit zu verwenden:

var abc = new xyz.VENDOR2.Type.abc();

oder

var abc = new OtherNameSpace.abc();
Zunair
quelle
4
Wie kann dies jedoch erreicht werden, wenn auf ein NUGET-Paket verwiesen wird, auf das anstelle einer regulären DLL verwiesen wird?
Bunkerdive
@bunkerdive Es wird höchstwahrscheinlich mit oder ohne NuGet-Paket genauso funktionieren. Wenn Sie ein NuGet-Paket installieren, sollten Verweise auf die Assemblys im Paket automatisch zu Ihrem Visual Studio-Projekt hinzugefügt werden. Schauen Sie unter dem Knoten Referenzen unter Ihrem Projekt im Ansichtsfenster * Solution Explorer "nach.
Kenny Evitt
1

Sie können Aliase für die verschiedenen Namespaces und / oder Typen verwenden:

So würde es aussehen:

using other = sssssss.a;
namespace ConsoleApplication1
{
    public class a 
    {
        public string ff { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            other s = new other();
            a b = new a();
        }
    }
}
namespace sssssss 
{

    public class a
    {
        public string ff { get; set; }
    }
}

MSDN

Igarioshka
quelle
0

Vielleicht können Sie es austricksen, indem Sie eine namespaceder Assemblys ändern. In diesem Fall ist der vollständig qualifizierte Name einer Assembly COMMONTYPEnicht gleich einer anderen, und möglicherweise kann dies Ihr Problem mit Konflikten in der 3. DLL lösen.

Hoffe das hilft.

Tigran
quelle
Leider kann ich das nicht tun, da ich die .NET-Assembly aus einer vorhandenen COM-DLL mit tlbimp generiere.
Kou S Hal