Frage

Kann jemand erklärt das folgende Verhalten?

Zusammenfassend: Wenn Sie erstellen mehrere CLS-kompatibel Bibliotheken in Visual Studio 2008 und haben sie einen gemeinsamen Namensraum root teilen, eine Bibliothek eine andere Bibliothek Referenzierung wird erfordert Verweise auf die Bibliothek Referenzen, obwohl sie diese nicht konsumieren.

Es ist ziemlich schwierig, in einem einzigen Satz zu erklären, aber hier sind Schritte, um das Verhalten (achten Sie genau auf die Namespaces) zu reproduzieren:

Erstellen Sie eine Bibliothek mit dem Namen LibraryA und eine einzige Klasse zu dieser Bibliothek hinzufügen:

namespace Ploeh
{
    public abstract class Class1InLibraryA
    {
    }
}

Stellen Sie sicher, dass die Bibliothek ist CLS-konform durch [assembly: CLSCompliant(true)] zu AssemblyInfo.cs hinzufügen.

Erstellen Sie eine andere Bibliothek namens BibliothekB und Referenz LibraryA. Fügen Sie die folgenden Klassen BibliothekB:

namespace Ploeh.Samples
{
    public class Class1InLibraryB : Class1InLibraryA
    {
    }
}

und

namespace Ploeh.Samples
{
    public abstract class Class2InLibraryB
    {
    }
}

Stellen Sie sicher, dass BibliothekB ist auch CLS-kompatibel.

Beachten Sie, dass Class1InLibraryB von einem Typ in LibraryA leitet, während Class2InLibraryB nicht.

Jetzt eine dritte Bibliothek namens LibraryC und Referenz BibliothekB (aber nicht LibraryA) erstellen. Fügen Sie die folgende Klasse:

namespace Ploeh.Samples.LibraryC
{
    public class Class1InLibraryC : Class2InLibraryB
    {
    }
}

Dies sollte noch kompilieren. Beachten Sie, dass Class1InLibraryC aus der Klasse in BibliothekB ergibt sich, dass verwendet keine Typen von LibraryA .

Beachten Sie auch, dass Class1InLibraryC in einem Namensraum definiert ist, die in BibliothekB definierten Teil der Namespace-Hierarchie ist.

Bisher hat LibraryC keinen Hinweis auf LibraryA, und da es keine Typen von LibraryA verwendet, stellt die Lösung.

Jetzt LibraryC CLS-kompatibel sowie machen. Plötzlich stellt die Lösung nicht mehr, diese Fehlermeldung zu geben:

  

Der Typ ‚Ploeh.Class1InLibraryA‘ ist in einer Baugruppe definiert, die nicht verwiesen wird. Sie müssen einen Verweis auf Assembly 'Ploeh, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null' hinzuzufügen.

Sie können die Lösung machen kompilieren wieder in eine der folgenden Möglichkeiten:

  • Entfernen CLS-Kompatibilität von LibraryC
  • Fügen Sie einen Verweis auf LibraryA (auch wenn Sie es nicht brauchen)
  • Ändern Sie den Namespace in LibraryC, so dass es nicht Teil BibliothekB der Namespace-Hierarchie (beispielsweise auf Fnaah.Samples.LibraryC)
  • ist
  • ändern Sie den Namensraum von Class1InLibraryB (das heißt, die ein nicht von LibracyC verwendet), so dass es nicht in LibraryC der Namespace-Hierarchie nicht liegen (zum Beispiel auf Ploeh.Samples.LibraryB)

Es scheint, dass es einige seltsame Zusammenspiel zwischen der Namespace-Hierarchie und CLS-Kompatibilität.

Um dieses Problem lösen kann oben durch Kommissionierung eine der Optionen in der Liste getan werden, aber jeder kann den Grund hinter diesem Verhalten erklären?

War es hilfreich?

Lösung

Ich hatte einen Blick in die offiziellen Dokumente für den CLS ( http: // msdn.microsoft.com/en-us/netframework/aa569283.aspx ), aber mein Kopf explodiert, bevor ich eine einfache Antwort finden konnte.

Aber ich denke, die Basis ist, dass der Compiler, um die CLS-Kompatibilität von LibraryC zu überprüfen, in mögliche Namenskonflikte mit LibraryA aussehen muss.

Der Compiler muss alle „Teile eines Typs, der zugänglich oder sichtbar außerhalb der definierenden Versammlung sind“ überprüfen (CLS Regel 1).

Da die öffentliche Klasse Class1InLibraryC Class2InLibraryB erbt, muss er die CLS-Kompatibilität gegen LibraryA überprüfen und, insbesondere, weil „Ploeh. *“ Ist jetzt „im Rahmen“ für CLS Regel 5 „Alle Namen in einem CLS-kompatibelen Umfang eingeführt wird sein verschieden unabhängig von Art“.

Ändern entweder den Namensraum von Class1InLibraryB oder Class1InLibraryC, so dass sie scheint verschieden worden mehr die Compiler gibt es keine Chance für einen Namenskonflikt zu überzeugen.

Wenn Sie die Option wählen (2), die Referenz hinzufügen und kompiliert, werden Sie sehen, dass der Verweis tatsächlich markiert ist nicht in den resultierenden Anordnung Meta-Daten, so ist dies eine Zusammenstellung / Verifizierung Zeitabhängigkeit nur.

Andere Tipps

Beachten Sie, dass der CLS ein Satz von Regeln ist, die erzeugten Baugruppen gelten und die Interoperabilität zwischen den Sprachen zu unterstützen. In gewissem Sinne, definiert sie die kleinste gemeinsame Teilmenge von Regeln, die eine Art folgen muß, um sicherzustellen, dass sie die Sprache und plattformunabhängig ist. CLS-Compliance auch gilt nur für Gegenstände, die sichtbar außerhalb ihrer definieren Montage sind.

auf einige der Suche der Richtlinien CLS-konformen Code sollte wie folgt vor:

  • Vermeiden Sie die Verwendung von Namen häufig als Schlüsselwörter in Programmiersprachen verwendet.
  • Nicht erwarten Nutzer des Rahmens der Lage sein, verschachtelte Typen an Autor.
  • Nehmen wir an, Implementierungen von Methoden mit dem gleichen Namen und Unterschrift auf verschiedenen Schnittstellen unabhängig sind.

Die Regeln zur Bestimmung CLS-Compliance sind:

  • Wann wird eine Baugruppe keine explizite System.CLSCompliantAttribute tragen, soll es sein angenommen System.CLSCompliantAttribute (false).
  • tragen
  • standardmäßig ein Typ erbt das CLS-Compliance-Attribut seines einschließenden Typs (für verschachtelte Typen) oder erwirbt das Niveau der Einhaltung seine Anordnung angebracht (für Top-Level-Typen).
  • standardmäßig andere Mitglieder (Methoden, Felder, Eigenschaften und Ereignisse), um die CLS-Konformität ihrer Art erben.

Nun, so weit wie die Compiler angehen, (CLS Regel 1) es muss in der Lage, die Regeln für die CLS-Compliance auf alle Informationen anzuwenden, die außerhalb der Assembly exportiert werden und halten einen Typen CLS-kompatibel zu sein, wenn alle seine öffentlich zugängliche Teile (jene Klassen, Interfaces, Methoden, Felder, Eigenschaften und Ereignisse, die in einer anderen Baugruppe Code verfügbar sind Ausführung) entweder

  • haben Unterschriften, die nur aus CLS-konformen Typen oder
  • als nicht CLS-kompatibel speziell markiert.

Mit dem CTS-Regeln, ein Bereich ist einfach eine Gruppe / Sammlung von Namen und innerhalb eines Bereichs ein Name auf mehrere Entitäten beziehen, solange sie von verschiedenen Arten sind (Methoden, Felder, verschachtelte Typen, Eigenschaften, Ereignisse) oder hat verschiedene Signaturen. Ein benannte Unternehmen seinen Namen genau ein Umfang in so um sowohl einen Umfang dieses Eintrags zu identifizieren und ein Name angewandt werden muß. Der Umfang qualifiziert den Namen.

Da Typen genannt werden, werden die Namen der Typen gruppiert auch auf Bereiche in. Um in vollem Umfang einen Typen zu identifizieren, muss der Typname durch den Umfang qualifiziert werden. Typen-Namen werden von der Versammlung scoped, die die Umsetzung dieses Typs enthält.

Für Bereiche, die CLS-kompatibel, alle Namen müssen verschieden unabhängig von Art sein, es sei denn, die Namen sind identisch und gelöst durch Überlastung. In anderen Worten, während die CTS einen einzigen Typen ermöglicht es den gleichen Namen für ein Feld und ein Verfahren zu verwenden, das CLS nicht (CLS Regel 5).

Gehen wir noch einen Schritt weiter, ein CLS-konformen Typ darf nicht erfordern die Implementierung von Nicht-CLS-konformen Typen (CLS Regel 20) und muss erben auch von einem anderen CLS-Reklamationsart (CLS Regel 23).

Eine Baugruppe kann auf anderen Baugruppen abhängen, ob die Ausführungen im Rahmen einer Montagereferenz Ressourcen, die in oder im Besitz von einer anderen Baugruppe scoped werden.

  • Alle Verweise auf andere Baugruppen werden unter der Kontrolle des laufenden Montage Umfang aufgelöst.
  • Es ist immer möglich, der Montag Umfang eine bestimmte Implementierung zu bestimmen, in ausgeführt wird. Alle Ursprungsanforderungen von dieser Versammlung Umfang relativ zu diesem Rahmen gelöst werden.

Was letztlich alle dies bedeutet, ist, dass, um die Einhaltung eines Typs CLS zu überprüfen, muss der Compiler in der Lage sein, dass , um zu überprüfen alle öffentliche Teile dieses Typs sind auch CLS-kompatibel. Das bedeutet, dass es muss sicherstellen, dass der Name in einem Umfang einzigartig ist, dass es nicht auf Nicht-CLS-kompatibel abhängt Typen für Teile ihrer eigenen Implementierung und dass es erbt von anderen Typen, die auch CLS-kompatibel sind. Der einzige Weg für sie, dies zu tun ist, indem alle den Arsch untersuchenemblies, dass die Typenbezeichnungen.

Beachten Sie, dass die Build-Schritt in Visual Studio ist im Wesentlichen ein GUI-Wrapper um MSBuild ausgeführt wird, die letztlich nichts anderes als eine scripted Art und Weise ist es, die C # Kommandozeilen-Compiler aufzurufen. Damit der Compiler CLS-Einhaltung eines Typs zu überprüfen, muss er wissen, und der Lage sein, alle Baugruppen zu finden, die Referenzen geben (nicht das Projekt). Da es durch MSBuild und schließlich Visual Studio, die einzige Möglichkeit für Visual Studio (MSBuild) es dieser Baugruppen zu informieren genannt wird, ist von ihnen als Referenzen einschließlich.

Natürlich, da der Compiler in der Lage ist, um herauszufinden, dass es „fehlt“ Referenzen, um CLS-Einhaltung zu überprüfen und erfolgreich zu kompilieren, wäre es schön gewesen, wenn es einfach enthielt diesen Bezug automatisch in unserem Namen haben könnte. Das Problem hierbei ist bei der Bestimmung , die Version der Assembly enthalten und mit , die Montage auf dem Dateisystem ist. Durch Erzwingen der Entwickler, dass die Informationen zur Verfügung zu stellen, hilft der Compiler Garantie, dass es die richtige Information gegeben wird. Dies hat auch den Nebeneffekt, dass alle abhängigen Assemblys die Debug/bin oder Release/bin Ordner während des Build kopiert werden, so dass sie im richtigen Verzeichnis sind, wenn die Anwendung ausgeführt wird, nachdem es kompiliert wurde.

Das Problem wird in Roslyn befestigt, die in Visual Studio 14
verfügbar ist Ab Juli 2014 ist die aktuelle CTP verfügbar .
Siehe dieser Bug-Report für Details.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top