[.net] Атрибут InternalsVisibleTo не работает



Answers

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

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

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

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

Question

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

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

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




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

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

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

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




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




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

#using "AssemblyUnderTest.dll" as_friend

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

Colin




Предыдущие ответы с 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.

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




Вот макрос, который я использую для быстрого создания этого атрибута. Это немного взломанный, но он работает. На моей машине. Когда последний подписанный двоичный файл находится в /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



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

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

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

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

<Assembly: InternalsVisibleTo("friend_unsigned_B")>




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




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

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




Links