Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

Иногда это мелочи...

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

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

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

Стоит отметить, что если "другая" (тестовая) сборка написана на C++/CLI, а не C#/VB.Net, то нужно использовать следующее:

#using "AssemblyUnderTest.dll" as_friend

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

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

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

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:компилятор переключатель при составлении сборки друга (сборка, которая не содержит атрибута InternalsVisibleto).

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

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

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

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

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

Предыдущие ответы с PublicKey работали:(Визуальная студия 2015:ДОЛЖНО быть в одной строке, иначе он сообщит, что ссылка на сборку недействительна или на нее невозможно ссылаться.PublicKeyToken не сработал)

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

Спасибо @Джо

Чтобы получить открытый ключ дружественной сборки:

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

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

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

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

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

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

Чтобы добавить элемент «Получить открытый ключ сборки» в меню «Инструменты»

В Visual Studio щелкните Внешние инструменты в меню Инструменты.

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

Заполните поле «Команда», перейдя к 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 в локальный каталог, она может работать как положено.

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

НАКОНЕЦ, можно использовать неподписанные сборки:https://msdn.microsoft.com/en-us/library/bb384966.aspxВы должны убедиться, что обе собрания не подписаны, а атрибут Ассамблеи должен быть без информации об publickey:

<Assembly: InternalsVisibleTo("friend_unsigned_B")>

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

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

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

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

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

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

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

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

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

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

1- Подпишите тестовый проект: В Visual Studio перейдите в окно свойств тестовый проект и Подпишите сборку установив флажок с той же фразой в Подписание вкладка.

2- Создайте PublicKey для тестового проекта: Откройте командную строку Visual Studio (например.Командная строка разработчика для VS 2017).Перейдите в папку, где находится файл .dll. тестовый проект существует.Создайте открытый ключ с помощью sn.exe:

sn -Tp TestProject.dll

Обратите внимание, что аргументом является -Tp, а не -tp.

3- Введите PublicKey в тестируемый проект: Перейдите к файлу AssemblyInfo.cs в проект, который нужно протестировать и добавьте эту строку с PublicKey, созданным на предыдущем шаге:

[сборка:InternalsVisibleTo("имя сборкитестпроекта, Публичный ключ=2066212d128683a85f31645c60719617ba512c0bfdba6791612ed56350368f6cc40a17b4942ff16cda9e760684658fa3f357c137a1005b04cb00240000048000 0094000000060200000024000052534131000400000100010065fe67a14eb30ffcdd99880e9d725f04e5c720dffc561b23e2953c34db8b7c5d4643f476408ad1b 1e28d6bde7d64279b0f51bf0e60be2d383a6c497bf27307447506b746bd2075")]

Не забудьте заменить указанный выше PublicKey своим.

4- Сделайте приватный метод внутренним: В тестируемом проекте измените модификатор доступа метода на внутренний.

внутренняя статика void DoSomething(){...}

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top