Атрибут InternalsVisibleTo не работает

Я пытаюсь использовать атрибут сборки InternalsVisibleTo чтобы мои внутренние classы в библиотеке classов .NET были видны моему модульному тестовому проекту. По какой-то причине я продолжаю получать сообщение об ошибке:

«MyClassName» недоступно из-за уровня защиты

Обе сборки подписаны, и у меня есть правильный ключ, указанный в объявлении атрибута. Есть идеи?

Вы абсолютно уверены, что у вас есть правильный открытый ключ, указанный в атрибуте? Обратите внимание, что вам нужно указать полный открытый ключ, а не только токен открытого ключа. Это выглядит примерно так:

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

Это 320 или около того шестнадцатеричных цифр. Не знаете, почему вам нужно указать полный открытый ключ – возможно, с помощью только токена открытого ключа, который используется в других ссылках на сборку, было бы легче кому-то подделать личность сборки сборщика.

Другая возможная «gotcha»: имя compilationа друзей, указанное вами в InternalsVisibleToAttribute должно точно соответствовать имени вашей сборки друга, как показано в свойствах проекта друга (на вкладке «Приложение»).

В моем случае у меня был проект Thingamajig и сопутствующий проект ThingamajigAutoTests (имена изменены, чтобы защитить виновных), которые произвели неподписанные сборки. Я должным образом добавил атрибут [assembly: InternalsVisibleTo( "ThingamajigAutoTests" )] в файл Thingamajig \ AssemblyInfo.cs и закомментировал атрибуты AssemblyKeyFile и AssemblyKeyName как указано выше. Thingamajig проект построен только штраф, но его внутренние члены упорно не обнаруживаться в проекте автотестов.

После большой царапины головы я перепроверил ThingamajigAutoTests проекта ThingamajigAutoTests и обнаружил, что имя сборки было указано как «ThingamajigAutoTests.dll». Bingo – я добавил расширение «.dll» к имени сборки в атрибуте InternalsVisibleTo , и куски встали на свои места.

Иногда это самые маленькие вещи …

Если ваши сборки не подписаны, но вы по-прежнему получаете ту же ошибку, проверьте файл AssemblyInfo.cs для любой из следующих строк:

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

Вкладка свойств по-прежнему будет показывать вашу сборку как unsigned, если присутствуют (или оба) этих строк, но атрибут InternalsVisibleTo рассматривает сборку с этими строками как сильно подписанную. Просто удалите (или запишите) эти строки, и это должно сработать для вас.

Стоит отметить, что если assembly «друзей» (тестов) написана на C ++ / CLI, а не на C # / VB.Net, вам необходимо использовать следующее:

 #using "AssemblyUnderTest.dll" as_friend 

вместо ссылки на проект или обычного оператора #using. По какой-то причине в пользовательском интерфейсе проекта нет никакого способа сделать это.

Colin

Вы можете использовать инструмент AssemblyHelper, который будет генерировать синтаксис InternalsVisibleTo для вас. Вот ссылка на последнюю версию . Просто отметьте, что он работает только для сильно названных сборок.

Вот макрос, который я использую для быстрого создания этого атрибута. Это немного взломанный, но он работает. На моей машине. Когда последний подписанный двоичный файл находится в /bin/debug . Etc equivocation и т. Д. Во всяком случае, вы можете видеть, как он получает ключ, так что это даст вам подсказку. Исправить / улучшить, как позволяет ваше время.

 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 

Вам нужно использовать переключатель / out: compiler при компиляции сборки Friend (assembly, которая не содержит атрибут InternalsVisibleTo).

Компилятор должен знать имя скомпилированной сборки, чтобы определить, следует ли рассматривать сборку в сборке друзей.

В дополнение ко всему вышесказанному, когда все кажется правильным, но друг узел упорно отказывается видеть любые внутренние, перезарядка решение или перезапуска Visual Studio может решить эту проблему.

В моем случае с использованием VS.Net 2015 мне нужно было подписать BOTH- сборки (если хотя бы одна assembly должна быть подписана или вы хотите ссылаться на открытый ключ вашей сборки).

Мой проект вообще не использовал подпись. Поэтому я начал добавлять знак знака в свою тестовую библиотеку и использовать InternalsVisibleTo-Attribute в базовой библиотеке моего проекта. Но VS.Net всегда объяснял, что не может получить доступ к методам друзей.

Когда я начал подписывать базовую библиотеку (это может быть тот же самый или другой знаковый ключ – пока вы подписываете базовую библиотеку), VS.Net сразу мог работать как ожидалось.

Предыдущие ответы с PublicKey работали: (Visual Studio 2015: НЕОБХОДИМО быть в одной строке, в противном случае он жалуется, что ссылка на сборку недействительна или не может ссылаться. PublicKeyToken не работал)

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

Благодаря @Joe

Чтобы получить открытый ключ сборки друга:

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

Внутри командной строки разработчика (Startup> Programs> Visual Studio 2015> Инструменты Visual Studio> Командная строка разработчика для VS2015). Благодаря @Ian G.

Хотя последний штрих, который заставлял меня работать для меня после того, как это было выше, заключалось в том, чтобы подписать проект библиотеки друзей так же, как и подписанный проект библиотеки. Поскольку это была новая тестовая библиотека, она еще не была подписана.

Вы должны создать новый полный открытый ключ для сборки, а затем указать атрибут для сборки.

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

Следуйте приведенным ниже шагам MSDN, чтобы создать новый полный открытый ключ для сборки из visual studio.

Чтобы добавить элемент «Общий доступ к сборке» в меню «Сервис»

В Visual Studio выберите « Внешние инструменты» в меню «Инструменты».

В диалоговом окне «Внешние инструменты» нажмите « Добавить» и введите «Открытый ключ сборки» в поле «Название».

Заполните поле Command, перейдя на sn.exe. Он обычно устанавливается в следующем месте: C: \ Program Files (x86) \ Microsoft SDK \ Windows \ v7.0a \ Bin \ x64 \ sn.exe .

В поле «Аргументы» введите следующее (с учетом регистра): -Tp $ (TargetPath) . Установите флажок Использовать выход.

Нажмите « ОК» . Новая команда добавляется в меню «Инструменты».

Всякий раз, когда вам нужен токен открытого ключа сборки, которую вы разрабатываете, щелкните команду «Получить общий ключ сборки» в меню «Инструменты», а токен открытого ключа появится в окне «Вывод».

Другая возможность, которая может быть сложной для отслеживания, в зависимости от того, как написан ваш код.

  1. Вы вызываете внутренний метод, определенный в X из другой сборки Y
  2. Подпись метода использует внутренние типы, определенные в Z
  3. Затем вам нужно добавить [InternalsVisibleTo] в X И в Z

Например:

 // In X internal static class XType { internal static ZType GetZ() { ... } } // In Y: object someUntypedValue = XType.GetZ(); // In Z: internal class ZType { ... } 

Если у вас есть это, как описано выше, где вы не имеете в виду ZType непосредственно в Y, добавив Y в качестве друга X, вы можете быть мистифицированы, почему ваш код все еще не компилируется.

В этом случае ошибка компиляции может быть более полезной.

Применяется только в том случае, если вам нравится хранить неподписанные сборки как неподписанную сборку (и не хотите подписывать ее по нескольким причинам):

Остается еще один момент: если вы скомпилируете базовую библиотеку из VS.Net в локальный каталог, она может работать как ожидалось.

НО: Как только вы скомпилируете свою базовую библиотеку на сетевой диск, применяются политики безопасности, и assembly не может быть успешно загружена. Это снова приводит к сбою VS.NET или компилятора при проверке соответствия PublicKey.

Наконец, можно использовать неподписанные сборки: https://msdn.microsoft.com/en-us/library/bb384966.aspx Вы должны убедиться, что сборки BOTH НЕ ПОДПИСАНЫ И атрибут Assembly должен быть без информации PublicKey:

В качестве побочного примечания, если вы хотите легко получить открытый ключ, не используя sn и не выясните его параметры, вы можете скачать удобную программу здесь . Он не только определяет открытый ключ, но также создает строку «assembly: InternalsVisibleTo …», которая готова к копированию в буфер обмена и вставлена ​​в ваш код.

Я просто решил аналогичную проблему с InternalsVisibleTo Attribute. Все казалось правильным, и я не мог понять, почему внутренний class, к которому я стремился, еще не был доступен.

Исправлена ​​проблема с заменой ключа от верхнего к нижнему регистру.

Я пишу это из разочарования. Убедитесь, что assembly, к которой вы предоставляете доступ, названа так, как вы ожидаете.

Я переименовал свой проект, но это не автоматически обновляет имя сборки. Щелкните правой кнопкой мыши свой проект и выберите « Свойства» . В разделе « Приложение» убедитесь, что пространство имен имен и по умолчанию – это то, что вы ожидаете.

Если у вас есть более одной ссылочной сборки – убедитесь, что все необходимые сборки имеют атрибут InternalsVisibleTo. Иногда это не очевидно, и нет сообщения, что вы должны добавить этот атрибут в одну сборку.

У меня такая же проблема. Ни одно из решений не работало.

В конце концов выяснилось, что проблема связана с тем, что class X явно реализует интерфейс Y, который является внутренним.

метод X.InterfaceMethod был недоступен, хотя я понятия не имею, почему.

Решением было бросить (X как YourInterface) .InterfaceMethod в тестовой библиотеке, а затем все сработало.

  • Сохранение пользовательских атрибутов в NSAttributedString
  • Пользовательские предупреждения компилятора
  • Как удалить отключенный атрибут с помощью jQuery (IE)
  • Атрибуты HttpPost и HttpGet в MVC: зачем использовать HttpPost?
  • Как работают classы атрибутов?
  • Каковы различия между AssemblyVersion, AssemblyFileVersion и AssemblyInformationalVersion?
  • Как установить динамическое значение в моем атрибуте
  • Получить перечисление из атрибута enum
  • Как удалить «onclick» с помощью JQuery?
  • Атрибут checkbox seleniumа "checked"
  • Пользовательские ассемблеры сборки
  • Давайте будем гением компьютера.