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



9 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» недоступно из-за уровня защиты

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




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

#using "AssemblyUnderTest.dll" as_friend

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

Colin




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



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




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

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




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

Остается еще один момент: если вы скомпилируете базовую библиотеку из 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 ...», которая готова к копированию в буфер обмена и вставлена ​​в ваш код.




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

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




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

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

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

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






Related