Atrybut InternalsVisibleTo nie działa

Próbuję użyć atrybutu InternalsVisibleTo assembly, aby moje wewnętrzne klasy w bibliotece klas.NET były widoczne dla mojego projektu testów jednostkowych. Z jakiegoś powodu ciągle dostaję komunikat o błędzie, który mówi:

'MyClassName' jest niedostępny ze względu na poziom ochrony

Oba zespoły są podpisane i mam poprawny klucz wymieniony w deklaracji atrybutów. Jakieś pomysły?

Author: abatishchev, 2008-09-20

19 answers

Czy jesteś absolutnie pewien, że masz poprawny klucz publiczny określony w atrybutie? Pamiętaj, że musisz podać pełny klucz publiczny, a nie tylko token klucza publicznego. Wygląda to tak:

[assembly: InternalsVisibleTo("MyFriendAssembly,
PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73
F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66
A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519
674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C140
6E2F553073FF557D2DB6C5")]
To jakieś 320 cyfr szesnastkowych. Nie wiem, dlaczego musisz podać pełny klucz publiczny - prawdopodobnie używając tylko tokena klucza publicznego, który jest używany w innych referencjach do asemblera, byłoby łatwiej komuś sfałszować tożsamość asemblera znajomego.
 102
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-02 21:12:44

Inny możliwy "mam cię": nazwa zespołu znajomego, który podałeś w InternalsVisibleToAttribute, musi dokładnie pasować do nazwy zespołu znajomego, jak pokazano we właściwościach projektu znajomego (w zakładce aplikacja).

W moim przypadku, miałem projekt Thingamajig i projekt towarzyszący ThingamajigAutoTests (nazwy zmienione w celu ochrony winnych), które oba produkowały niepodpisane zespoły. Dodałem atrybut [assembly: InternalsVisibleTo( "ThingamajigAutoTests" )] do thingamajig\AssemblyInfo.plik cs i skomentował AssemblyKeyFile i AssemblyKeyName atrybuty jak wspomniano powyżej. Projekt Thingamajig był dobrze zbudowany, ale jego członkowie wewnętrzni uparcie odmawiali pokazania się w projekcie autotest.

Po długim zadrapaniu głowy, ponownie sprawdziłem właściwości projektu ThingamajigAutoTests i odkryłem, że nazwa zestawu została określona jako " ThingamajigAutoTests.dll". Bingo - dodałem"dll " rozszerzenie do nazwy złożenia w atrybutie InternalsVisibleTo, a kawałki spadły na swoje miejsce.

Czasami to najmniejsze rzeczy...

 40
Author: John Beyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-26 18:01:04

Jeśli Twoje zespoły nie są podpisane, ale nadal masz ten sam błąd, sprawdź swoje AssemblyInfo.plik cs dla jednej z następujących linii:

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

Zakładka properties nadal będzie wyświetlać skład jako niepodpisany, jeśli któryś z tych wierszy (lub oba) są obecne, ale atrybut InternalsVisibleTo traktuje skład z tymi wierszami jako silnie podpisany. Po prostu usuń (lub skomentuj) te linie, a to powinno działać dobrze dla Ciebie.

 37
Author: Skimedic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-29 16:54:46

Warto zauważyć, że jeśli assembly" friend " (testy) jest napisany w C++ / CLI, a nie w C# / VB. Net, to należy użyć następującego:

#using "AssemblyUnderTest.dll" as_friend

Zamiast odniesienia do projektu lub zwykłej deklaracji #using. Z jakiegoś powodu nie ma sposobu, aby to zrobić w interfejsie odniesienia do projektu.

 12
Author: Colin Desmond,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-20 12:56:28

Możesz użyć narzędzia AssemblyHelper , które wygeneruje dla ciebie wewnętrzną składnię. Oto link do najnowszej wersji . Zauważ, że działa tylko dla silnie nazwanych zespołów.

 9
Author: Vadim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-04 16:50:45

Oto makro, którego używam do szybkiego wygenerowania tego atrybutu. Jest trochę szorstki, ale działa. Na mojej maszynie. Gdy ostatni podpisany plik binarny znajduje się w /bin/debug. Itd. W każdym razie, możesz zobaczyć, jak dostaje klucz, więc to da ci wskazówkę. Naprawić / poprawić jak Twój czas pozwala.

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
 5
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-22 17:36:45

Oprócz wszystkich powyższych, gdy wszystko wydaje się być poprawne, ale przyjaciel assembly uparcie odmawia zobaczenia jakichkolwiek wewnętrznych, przeładowanie rozwiązania lub ponowne uruchomienie Visual Studio może rozwiązać problem.

 5
Author: Alex J,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-17 12:03:10

Musisz użyć przełącznika / out: compiler podczas kompilacji friend assembly (assembly, który nie zawiera atrybutu InternalsVisibleTo).

Kompilator musi znać nazwę kompilowanego zestawu, aby określić, czy Wynikowy zestaw powinien być uważany za zestaw przyjacielski.

 4
Author: Ash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-20 03:16:25

Wymagane jest wygenerowanie nowego pełnego klucza publicznego dla złożenia, a następnie określenie atrybutu do złożenia.

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

Wykonaj poniższe kroki MSDN , aby wygenerować nowy pełny klucz publiczny dla złożenia z programu visual studio.

Aby dodać pozycję klucz publiczny Get Assembly do menu Narzędzia

W Visual Studio kliknij External Tools w menu Narzędzia.

W oknie dialogowym Narzędzia zewnętrzne kliknij Dodaj i wprowadź Get Assembly Public Klucz w polu Tytuł.

Wypełnij pole poleceń, przeglądając sn.exe. Zazwyczaj jest instalowany w następującej lokalizacji: C:\Program Files (x86) \ Microsoft SDKs \ Windows \ v7. 0a \ Bin \ x64 \ sn.exe .

W polu Arguments wpisz następujący (rozróżniający wielkość liter): - TP $(TargetPath) . Zaznacz pole wyboru Użyj okna wyjścia.

Kliknij OK . Nowe polecenie jest dodawane do menu Narzędzia.

Gdy potrzebujesz Tokena klucza publicznego zgromadzenia, jesteś rozwijając, kliknij polecenie Get Assembly public Key w menu Narzędzia, a token klucza publicznego pojawi się w oknie wyjściowym.

 3
Author: Murugan Sivananantha Perumal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-18 18:13:59

W moim przypadku za pomocą VS.Net 2015, musiałem podpisać oba zespoły (Jeśli co najmniej 1 Zgromadzenie ma być podpisane lub chcesz odwołać się do klucza publicznego swojego zgromadzenia).

Mój projekt w ogóle nie używał podpisywania. Zacząłem więc dodawać klucz znakowy do mojej biblioteki testowej i używać atrybutu InternalsVisibleTo w bibliotece bazowej mojego projektu. Ale VS.Net zawsze tłumaczył, że nie ma dostępu do metod przyjacielskich.

Kiedy zacząłem podpisywać bibliotekę bazową (może być taka sama lub kolejny klucz znakowy - o ile podpiszesz bibliotekę bazową), VS.Net natychmiast był w stanie pracować zgodnie z oczekiwaniami.

 3
Author: Jochen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-25 15:36:44

Poprzednie odpowiedzi z PublicKey działały: (Visual Studio 2015: musi być w jednej linii, w przeciwnym razie narzeka, że odniesienie do montażu jest nieprawidłowe lub nie może się odwołać. PublicKeyToken nie działa)

[assembly: InternalsVisibleTo("NameSpace.MyFriendAssembly, PublicKey=0024000004800000940000000602000000240000525341310004000001000100F73F4DDC11F0CA6209BC63EFCBBAC3DACB04B612E04FA07F01D919FB5A1579D20283DC12901C8B66A08FB8A9CB6A5E81989007B3AA43CD7442BED6D21F4D33FB590A46420FB75265C889D536A9519674440C3C2FB06C5924360243CACD4B641BE574C31A434CE845323395842FAAF106B234C2C1406E2F553073FF557D2DB6C5")]
Dzięki @ Joe

Aby uzyskać klucz publiczny zespołu znajomego:

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

Wewnątrz wiersza polecenia programisty (uruchamianie > programy > Visual Studio 2015 > narzędzia Visual Studio > Wiersz polecenia programisty dla VS2015). Dzięki @ Ian G.

Chociaż, ostatnim akcentem, który sprawił, że działał dla mnie po powyższym, było podpisanie projektu biblioteki mojego przyjaciela w taki sam sposób, w jaki projekt biblioteki do udostępnienia jest podpisany. Ponieważ była to nowa biblioteka testowa, nie została jeszcze podpisana.

 2
Author: Micaël,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-14 15:57:50

Kolejna możliwość, która może być trudna do wyśledzenia, w zależności od tego, jak jest napisany kod.

  1. wywołujesz wewnętrzną metodę zdefiniowaną w X z innego zbioru Y
  2. podpis metody wykorzystuje typy wewnętrzne zdefiniowane w Z
  3. Następnie musisz dodać [InternalsVisibleTo] W X I W z

Na przykład:

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

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

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

Jeśli masz to napisane jak wyżej, gdzie nie odnosisz się bezpośrednio do ZType w Y, po dodaniu Y jako przyjaciela X, możesz może być dziwne, dlaczego twój kod nadal nie jest kompilowany.

Błąd kompilacji może być zdecydowanie bardziej pomocny w tym przypadku.

 2
Author: Tatiana Racheva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-08 00:10:49

Piszę to z frustracji. Upewnij się, że zespół, do którego przyznajesz dostęp, jest nazwany zgodnie z oczekiwaniami.

Zmieniłem nazwę projektu, ale to nie powoduje automatycznej aktualizacji nazwy zestawu. Kliknij prawym przyciskiem myszy projekt i kliknij Właściwości. W aplikacji Upewnij się, że Nazwa zestawu i domyślna Przestrzeń nazw są tym, czego oczekujesz.

 2
Author: Kameron Kincade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-19 00:25:44

Stosuje się tylko wtedy, gdy chcesz zachować niepodpisane zespoły jako niepodpisane zespoły (i nie chcesz go podpisywać z kilku powodów):

Jest jeszcze jedna kwestia: jeśli skompilujesz swoją bibliotekę bazową z VS.Net do katalogu lokalnego, może działać zgodnie z oczekiwaniami.

Ale: gdy tylko skompilujesz bibliotekę bazową na dysku sieciowym, obowiązują zasady bezpieczeństwa i nie można załadować zestawu. To znowu powoduje VS.NET lub kompilator, który nie sprawdzi się przy sprawdzaniu mecz.

Wreszcie, możliwe jest użycie niepodpisanych zestawów: https://msdn.microsoft.com/en-us/library/bb384966.aspx Musisz upewnić się, że oba zespoły nie są podpisane A atrybut Assembly musi być bez Informacji Publicznej:

<Assembly: InternalsVisibleTo("friend_unsigned_B")>

 1
Author: Jochen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-25 15:34:20

Miałem ten sam problem. Żadne z rozwiązań nie zadziałało.

Ostatecznie odkryłem, że problem był spowodowany jawnie implementującym interfejs Y klasy X, który jest wewnętrzny.

Metoda X. InterfaceMethod była niedostępna, choć nie mam pojęcia dlaczego.

Rozwiązaniem było rzucenie (X jako Twejinterface).InterfaceMethod w bibliotece testowej, a potem wszystko działało.

 1
Author: Sentinel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-29 15:50:16

Na marginesie, jeśli chcesz łatwo uzyskać klucz publiczny bez konieczności używania sn i poznawania jego opcji, możesz pobrać przydatny program tutaj. Nie tylko określa klucz publiczny, ale także tworzy " assembly :InternalsVisibleTo..."linia gotowa do skopiowania do schowka i wklejenia do kodu.

 0
Author: Bill W,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-26 18:25:51

Właśnie rozwiązałem podobny problem z atrybutem InternalsVisibleTo. Wszystko wydawało się w porządku i nie mogłem zrozumieć, dlaczego wewnętrzna Klasa, do której celowałem, nadal nie była dostępna.

Zmiana wielkości liter klawisza z wielkiej na małą rozwiązała problem.

 0
Author: Keysharpener,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-26 09:20:02

Jeśli masz więcej niż 1 odwołany assembly-sprawdź, czy wszystkie niezbędne Assembly mają atrybut InternalsVisibleTo. Czasami nie jest to oczywiście, i nie ma wiadomości, że trzeba dodać ten atrybut do else jeden assembly.

 0
Author: VladExL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-29 14:00:50

1- podpisz projekt testowy: w Visual Studio przejdź do okna Właściwości projektu testowego i podpisz zespół zaznaczając pole wyboru z tą samą frazą w zakładce podpisywanie .

2- Utwórz publicznie dla projektu testowego: Otwórz wiersz poleceń programu Visual Studio (np. Wiersz poleceń dewelopera dla VS 2017). Przejdź do folderu gdzie .plik dll istnieje projekt testowy. Utwórz klucz publiczny przez sn.exe:

Sn-TP TestProject.dll

Zauważ, że argumentem jest-Tp, ale nie -tp.

3- wprowadź PublicKey do testowanego projektu: Przejdź do AssemblyInfo.plik cs w projekcie do przetestowania i dodaj tę linijkę do pliku utworzonego w poprzednim kroku:

[assembly: InternalsVisibleTo ("TestProjectAssemblyName , PublicKey=2066212d128683a85f31645c60719617ba512c0bfdba6791612ed56350368f6cc40a17b4942ff16cda9e760684658fa3f357c137a1005b04cb002400000480000094000000060200000024000052534131000400000100010065fe67a14eb30ffcdd99880e9d725f04e5c720dffc561b23e2953c34db8b7c5d4643f476408ad1b1e28d6bde7d64279b0f51bf0e60be2d383a6c497bf27307447506b746bd2075")]

Nie zapomnij wymienić powyższej strony na swoją.

4- Uczyń metodę prywatną wewnętrzną: w projekcie do przetestowania Zmień modyfikator dostępu metody na wewnętrzny.

Internal static void DoSomething () {...}

 0
Author: user3029066,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-03 11:56:16