Frage

Ich versuche, das zu verwenden InternalsVisibleTo Assembly-Attribut, um meine internen Klassen in einer .NET-Klassenbibliothek für mein Unit-Test-Projekt sichtbar zu machen.Aus irgendeinem Grund erhalte ich immer wieder die Fehlermeldung:

Auf „MyClassName“ kann aufgrund seiner Schutzstufe nicht zugegriffen werden

Beide Assemblys sind signiert und ich habe den richtigen Schlüssel in der Attributdeklaration aufgeführt.Irgendwelche Ideen?

War es hilfreich?

Lösung

Sind Sie absolut sicher, dass im Attribut der richtige öffentliche Schlüssel angegeben ist?Beachten Sie, dass Sie den vollständigen öffentlichen Schlüssel angeben müssen, nicht nur das Public-Key-Token.Es sieht ungefähr so ​​aus:

[assembly: InternalsVisibleTo("MyFriendAssembly,
PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73
F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66
A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519
674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C140
6E2F553073FF557D2DB6C5")]

Es sind ungefähr 320 hexadezimale Ziffern.Ich bin mir nicht sicher, warum Sie den vollständigen öffentlichen Schlüssel angeben müssen. Möglicherweise wäre es für jemanden einfacher, die Identität der befreundeten Assembly zu fälschen, wenn nur das öffentliche Schlüsseltoken verwendet wird, das in anderen Assembly-Referenzen verwendet wird.

Andere Tipps

Ein weiterer möglicher "gotcha": der Name der Freundschaftsversammlung, die Sie in der angeben InternalsVisibleToAttribute muss exakt Passen Sie den Namen Ihrer Freundesversammlung an, wie in den Projekteigenschaften des Freundes (auf der Registerkarte Anwendung) gezeigt.

In meinem Fall hatte ich ein Projekt Thingamajig und ein Begleitprojekt ThingamajigAutoTests (Namen geändert, um die Schuldigen zu schützen), die beide unsignierte Versammlungen erzeugten. Ich habe das Attribut ordnungsgemäß hinzugefügt [assembly: InternalsVisibleTo( "ThingamajigAutoTests" )] Zu der Datei von DingAMAG ASSEMBLYINFO.CS und kommentierte die AssemblyKeyFile und AssemblyKeyName Attribute wie oben erwähnt. Das Thingamajig Das Projekt hat gut gebaut, aber seine internen Mitglieder weigerten sich hartnäckig, im Autotest -Projekt zu erscheinen.

Nach viel Kratzern habe ich das überprüft ThingamajigAutoTests Projekteigenschaften und stellten fest, dass der Name der Versammlung als "ThingAMAJigautotests.dll" angegeben wurde. Bingo - Ich habe die Erweiterung ".dll" dem Montagennamen in der hinzugefügt InternalsVisibleTo Attribut, und die Stücke fielen zusammen.

Manchmal sind es die kleinsten Dinge ...

Wenn Ihre Baugruppen nicht unterschrieben sind, aber Sie immer noch den gleichen Fehler erhalten, überprüfen Sie Ihre AssemblyInfo.cs -Datei für eine der folgenden Zeilen:

[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]

Auf der Registerkarte Eigenschaften werden Ihre Baugruppe weiterhin als unsigniert angezeigt, wenn entweder (oder beide) dieser Linien vorhanden sind, aber das InternalSVisibleto -Attribut behandelt eine Anordnung mit diesen Linien als stark signiert. Löschen (oder kommentieren Sie diese Zeilen einfach aus) und es sollte für Sie gut funktionieren.

Es ist erwähnenswert, dass die "Freund" (Tests) (Tests) in C ++/CLI statt C#/vb.net geschrieben ist, dann müssen Sie Folgendes verwenden:

#using "AssemblyUnderTest.dll" as_friend

anstelle einer Projektreferenz oder der üblichen #using Aussage. Aus irgendeinem Grund gibt es keine Möglichkeit, dies in der UI der Projektreferenz zu tun.

Sie können verwenden AssemblyHelper -Werkzeug Das generiert für Sie die Innenvisvisibleto -Syntax. Hier ist Der Link zur neuesten Version. Beachten Sie nur, dass es nur für stark benannte Versammlungen funktioniert.

Hier ist ein Makro, mit dem ich dieses Attribut schnell generiere. Es ist ein bisschen hackig, aber es funktioniert. Auf meiner Maschine. Wenn der neueste signierte binäre ist in /bin/debug. Usw. Zweideutigkeit usw. Wie auch immer, Sie können sehen, wie es den Schlüssel erhält, so dass Sie einen Hinweis geben. Beheben/verbessern Sie sich, wenn Ihre Zeit erlaubt.

Sub GetInternalsVisibleToForCurrentProject()
    Dim temp = "[assembly:  global::System.Runtime.CompilerServices." + _
               "InternalsVisibleTo(""{0}, publickey={1}"")]"
    Dim projs As System.Array
    Dim proj As Project
    projs = DTE.ActiveSolutionProjects()
    If projs.Length < 1 Then
        Return
    End If

    proj = CType(projs.GetValue(0), EnvDTE.Project)
    Dim path, dir, filename As String
    path = proj.FullName
    dir = System.IO.Path.GetDirectoryName(path)
    filename = System.IO.Path.GetFileNameWithoutExtension(path)
    filename = System.IO.Path.ChangeExtension(filename, "dll")
    dir += "\bin\debug\"
    filename = System.IO.Path.Combine(dir, filename)
    If Not System.IO.File.Exists(filename) Then
        MsgBox("Cannot load file " + filename)
        Return
    End If
    Dim assy As System.Reflection.Assembly
    assy = System.Reflection.Assembly.Load(filename)
    Dim pk As Byte() = assy.GetName().GetPublicKey()
    Dim hex As String = BitConverter.ToString(pk).Replace("-", "")
    System.Windows.Forms.Clipboard.SetText(String.Format(temp, assy.GetName().Name, hex))
    MsgBox("InternalsVisibleTo attribute copied to the clipboard.")
End Sub

Sie müssen den Schalter für /out: compiler beim Kompilieren der Freundschaftsbaugruppe verwenden (die Baugruppe, die das Attribut „InternalSisibleto“ nicht enthält).

Der Compiler muss den Namen der Zusammenstellung des Versammlung kennen, um festzustellen, ob die resultierende Baugruppe als Freundesversammlung angesehen werden sollte.

Zusätzlich zu all dem oben genannten, wenn alles korrekt zu sein scheint, aber die Freundschaftsversammlung sich hartnäckig weigert, irgendwelche Interna zu sehen, Laden Sie die Lösung neu oder starten Sie Visual Studio neu kann das Problem lösen.

In meinem Fall musste ich mit Vs.NET 2015 unterschreiben BEIDE Versammlungen (wenn mindestens 1 Versammlung unterschrieben werden oder Sie auf den öffentlichen Schlüssel Ihrer Versammlung verweisen möchten).

Mein Projekt hat sich überhaupt nicht unterschrieben. Deshalb fügte ich in meiner Testbibliothek einen Zeichenschlüssel hinzu und verwendete die Basisbibliothek meines Projekts. Aber Vs.NET erklärte immer, dass es nicht auf die Freundesmethoden zugreifen konnte.

Als ich anfing, die Basisbibliothek zu unterschreiben (sie kann der gleiche oder andere Zeichenschlüssel sein - solange Sie die Basisbibliothek unterschreiben), konnte Vs.NET sofort wie erwartet arbeiten.

Frühere Antworten mit PublicKey funktionierten: (Visual Studio 2015: Muss in einer Zeile sein, ansonsten beschwert sich die Versammlungsreferenz ungültig oder kann nicht verwiesen. PublicKeyToken hat nicht funktioniert.

[assembly: InternalsVisibleTo("NameSpace.MyFriendAssembly, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C1406E2F553073FF557D2DB6C5")]

Vielen Dank an @joe

Um den öffentlichen Schlüssel der Freundschaftsversammlung zu erhalten:

sn -Tp path\to\assembly\MyFriendAssembly.dll

In einer Entwicklungseingabeaufforderung (Startup> Programme> Visual Studio 2015> Visual Studio Tools> Entwicklereingabeaufforderung für VS2015). Vielen Dank an @ian G.

Der letzte Touch, der es für mich nach dem oben genannten zum Laufen brachte, bestand jedoch darin, mein Freund der Freundesbibliothek genauso zu unterschreiben, wie das Projekt der Bibliothek zu teilen ist. Da es sich um eine neue Testbibliothek handelte, wurde sie noch nicht unterschrieben.

Sie müssen einen neuen vollständigen öffentlichen Schlüssel für die Versammlung generieren und dann das Attribut für die Versammlung angeben.

[assembly: InternalsVisibleTo("assemblyname,
PublicKey="Full Public Key")]

Folgen Sie dem folgenden Msdn Schritte zur Generierung eines neuen vollständigen öffentlichen Schlüssels für die Versammlung von Visual Studio.

So fügen Sie dem Tools -Menü ein öffentliches Schlüsselelement für die Versammlung hinzu

Klicken Sie in Visual Studio Externe Werkzeuge im Tools -Menü.

Klicken Sie im Dialogfeld External Tools im Dialogfeld Hinzufügen und GET GET ASSEMBLY PUBLIC KEY IN DAS TITEL -KOBLE.

Füllen Sie das Befehlsfeld, indem Sie nach Sn.exe stöbern. Es ist normalerweise am folgenden Ort installiert: C: Programmdateien (x86) Microsoft SDKs Windows V7.0a bin x64 sn.exe.

Geben Sie im Feld Argumente Folgendes ein (Fallempfindlichkeit): -Tp $ (TargetPath). Wählen Sie das Kontrollkästchen Ausgangsfenster aus.

Klicken OK. Der neue Befehl wird dem Tools -Menü hinzugefügt.

Wenn Sie das öffentliche Key -Token der von Ihnen entwickelten Versammlung benötigen, klicken Sie im Menü "Tools

Eine andere Möglichkeit, die schwierig zu erfassen ist, je nachdem, wie Ihr Code geschrieben wird.

  1. Sie rufen eine interne Methode an, die in X aus einer anderen Baugruppe Y definiert ist
  2. Die Methodensignatur verwendet interne Typen, die in z definiert sind
  3. Sie müssen dann [InternalSVissibleto] in x und in z hinzufügen

Zum Beispiel:

// In X
internal static class XType
{
    internal static ZType GetZ() { ... }
}

// In Y:
object someUntypedValue = XType.GetZ();

// In Z:
internal class ZType { ... }

Wenn Sie es wie oben geschrieben haben, wo Sie sich nicht direkt in y auf ZTYPE beziehen, nachdem Sie Y als Freund von X hinzugefügt haben, werden Sie möglicherweise mystifiziert, warum Ihr Code immer noch nicht kompiliert wird.

Der Kompilierungsfehler könnte in diesem Fall definitiv hilfreicher sein.

Gilt nur, wenn Sie nicht signierte Baugruppen als nicht signierte Baugruppe aufbewahren möchten (und möchten sie aus mehreren Gründen nicht unterschreiben):

Es gibt noch einen weiteren Punkt: Wenn Sie Ihre Basisbibliothek von Vs.NET zu einem lokalen Verzeichnis kompilieren, kann dies wie erwartet funktionieren.

Aber: Sobald Sie Ihre Basisbibliothek zu einem Netzwerklaufwerk zusammenstellen, gelten Sicherheitsrichtlinien und die Montage kann nicht erfolgreich geladen werden. Dies führt erneut dazu, dass Vs.NET oder der Compiler beim Überprüfen des PublicKey -Spiels fehlschlägt.

Schließlich ist es möglich, nicht signierte Baugruppen zu verwenden:https://msdn.microsoft.com/en-us/library/bb384966.aspxSie müssen sicherstellen, dass beide Versammlungen nicht signiert sind und das Assembly -Attribut ohne öffentliche Informationen erfolgen muss:

<Assembly: InternalsVisibleTo("friend_unsigned_B")>

Ich schreibe das aus Frustration. Stellen Sie sicher, dass die Versammlung, auf die Sie den Zugriff erteilen, wie Sie erwartet werden.

Ich habe mein Projekt umbenannt, aber dies aktualisiert den Montage -Namen nicht automatisch. Klicken Sie mit der rechten Maustaste auf Ihr Projekt und klicken Sie auf Eigenschaften. Unter Anwendung, stellen Sie sicher, dass die Montage Name und Standard -Namespace sind was Sie erwarten.

Ich hatte das gleiche Problem. Keine der Lösungen hat funktioniert.

Schließlich entdeckte das Problem darauf, dass die Klasse X explizit die Schnittstelle y implementiert, die intern ist.

Die Methode X.Interfacemethod war nicht verfügbar, obwohl ich keine Ahnung habe warum.

Die Lösung bestand darin, (x als IhrInterface) zu gießen .Interfacemethod in der Testbibliothek und dann funktionierte die Dinge.

Als Randnotiz können Sie den öffentlichen Schlüssel problemlos erhalten, ohne SN verwenden zu müssen und seine Optionen herauszufinden, Sie können das handliche Programm herunterladen hier. Es bestimmt nicht nur den öffentlichen Schlüssel, sondern erstellt auch die Zeile "Assembly: InternalSVisibleto ...", die bereit ist, in die Zwischenablage kopiert und in Ihren Code eingefügt zu werden.

Ich habe gerade ein ähnliches Problem mit dem gelöst InternalsVisibleTo Attribut. Alles schien richtig zu sein und ich konnte nicht herausfinden, warum die interne Klasse, die ich zielte, noch nicht zugänglich war.

Das Ändern des Schlüssels des Schlüssels vom oberen in den unteren Fall hat das Problem festgelegt.

Wenn Sie mehr als 1 referenzierte Montage haben, überprüfen Sie, ob alle erforderlichen Baugruppen ein InternalSVISibleto -Attribut haben. Manchmal ist es offensichtlich nicht und keine Nachricht, dass Sie dieses Attribut in eine andere Versammlung hinzufügen müssen.

1- Unterschreiben Sie das Testprojekt: In Visual Studio gehen Sie zum Eigenschaftenfenster von das Testprojekt und Unterschreiben Sie die Baugruppe Durch Überprüfen des Kontrollkästchens mit demselben Satz in der Unterzeichnung Tab.

2- Erstellen Sie einen PublicKey für das Testprojekt: Öffnen Sie die Eingabeaufforderung der Visual Studio (z. B. Entwicklereingabeaufforderung für VS 2017). Gehen Sie zum Ordner, in dem die .dll -Datei von das Testprojekt existiert. Erstellen Sie einen öffentlichen Schlüssel über Sn.exe:

sn -TP testProject.dll

Beachten Sie, dass das Argument -tp, aber nicht -tp ist.

3- Stellen Sie den PublicKey in das zu testende Projekt ein: Gehen Sie zur Datei montaginfo.cs in das zu testende Projekt und fügen Sie diese Zeile mit dem im vorherigen Schritt erstellten PublicKey hinzu:

Assembly: InternaSVissibleto ("TestProjectAsSemblyName, Öffentlicher Schlüssel=2066212d128683a85f31645c60719617ba512c0bfdba6791612ed56350368f6cc40a17b4942ff16cda9e760684658fa3f357c137a1005b04cb002400000480000094000000060200000024000052534131000400000100010065fe67a14eb30ffcdd99880e9d725f04e5c720dffc561b23e2953c34db8b7c5d4643f476408ad1b1e28d6bde7d64279b0f51bf0e60be2d383a6c497bf27307447506b746bd2075")

Vergessen Sie nicht, den oben genannten PublicKey durch Ihren zu ersetzen.

4- Machen Sie die private Methode intern: Ändern Sie im zu testenden Projekt den Zugriffsmodifikator der Methode in intern.

interne statische void dosomething () {...}

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