Question

J'essaie d'utiliser l'attribut InternalsVisibleTo assembly pour rendre mes classes internes d'une bibliothèque de classes .NET visibles pour mon projet de test d'unité. Pour une raison quelconque, je continue à recevoir un message d'erreur indiquant:

  

'MyClassName' est inaccessible en raison de son niveau de protection

Les deux assemblys sont signés et la clé correcte est répertoriée dans la déclaration de l'attribut. Des idées?

Était-ce utile?

La solution

Êtes-vous absolument sûr d'avoir la bonne clé publique spécifiée dans l'attribut? Notez que vous devez spécifier la clé publique complète, pas seulement le jeton de clé publique. Cela ressemble à quelque chose comme:

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

C'est environ 320 chiffres hexadécimaux. Vous ne savez pas pourquoi vous devez spécifier la clé publique complète; éventuellement, avec uniquement le jeton de clé publique utilisé dans d'autres références d'assemblages, il serait plus facile pour quelqu'un d'usurper l'identité de l'assembly ami.

Autres conseils

Un autre " gotcha " possible: le nom de l'assembly ami que vous spécifiez dans le fichier InternalsVisibleToAttribute doit correspondre exactement au nom de l'assembly de votre ami, comme indiqué dans les propriétés du projet de l'ami (dans l'onglet Application).

Dans mon cas, j’avais un projet Thingamajig et un projet associé ThingamajigAutoTests (les noms ont été modifiés pour protéger les coupables), qui ont tous deux produit des assemblys non signés. J'ai dûment ajouté l'attribut [assembly: InternalsVisibleTo( "ThingamajigAutoTests" )] au fichier Thingamajig \ AssemblyInfo.cs et commenté les attributs AssemblyKeyFile et AssemblyKeyName comme indiqué ci-dessus. Le projet InternalsVisibleTo a bien été construit, mais ses membres internes ont refusé obstinément de se présenter au projet d’autotest.

Après de nombreuses critiques, j'ai revérifié les <=> propriétés du projet et découvert que le nom de l'assembly était spécifié comme & "ThingamajigAutoTests.dll &". Bingo - J'ai ajouté le & Quot; .dll & Quot; extension au nom de l'assemblage dans l'attribut <=> et les pièces se sont mises en place.

Parfois, ce sont les plus petites choses ...

Si vos assemblys ne sont pas signés, mais que vous obtenez toujours la même erreur, recherchez dans votre fichier AssemblyInfo.cs l'une des lignes suivantes:

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

L'onglet Propriétés affichera toujours votre assemblage comme non signé si l'une ou l'autre (ou les deux) de ces lignes sont présentes, mais l'attribut InternalsVisibleTo traite un assemblage avec ces lignes comme étant fortement signées. Supprimez simplement ces lignes (ou mettez-les en commentaires), et tout devrait bien fonctionner pour vous.

Il est à noter que si & "ami &"; (tests) assembly, il est écrit en C ++ / CLI et non en C # / VB.Net. Vous devez donc utiliser les éléments suivants:

#using "AssemblyUnderTest.dll" as_friend

au lieu d'une référence de projet ou de l'instruction #using habituelle. Pour une raison quelconque, il n'y a aucun moyen de le faire dans l'interface utilisateur de référence du projet.

Vous pouvez utiliser outil AssemblyHelper qui générera la syntaxe InternalsVisibleTo pour vous. Voici le lien vers la dernière version . Notez simplement que cela ne fonctionne que pour les assemblys fortement nommés.

Voici une macro que j'utilise pour générer rapidement cet attribut. C'est un peu hacky, mais ça marche. Sur ma machine. Lorsque le dernier binaire signé est dans /bin/debug. Etc équivoque, etc. De toute façon, vous pouvez voir comment il obtient la clé, ce qui vous donnera un indice. Corrigez / améliorez si votre temps le permet.

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

Vous devez utiliser le commutateur / out: compilateur lors de la compilation de l'assembly ami (l'assembly qui ne contient pas l'attribut InternalsVisibleTo).

Le compilateur doit connaître le nom de l'assemblage en cours de compilation afin de déterminer si l'assemblage obtenu doit être considéré comme un assemblage ami.

En plus de tout ce qui précède, lorsque tout semble correct, mais que l'assembly ami refuse obstinément de voir les éléments internes, le rechargement de la solution ou le redémarrage de Visual Studio peuvent résoudre le problème.

Dans mon cas d'utilisation de VS.Net 2015, je devais signer des assemblys BOTH (si au moins un assemblage doit être signé ou si vous souhaitez faire référence à la clé publique de votre assemblage).

Mon projet n'a pas du tout utilisé la signature. J'ai donc commencé à ajouter une clé de signature à ma bibliothèque de tests et à utiliser InternalsVisibleTo-Attribute dans la bibliothèque de base de mon projet. Mais VS.Net a toujours expliqué qu’il ne pouvait pas accéder aux méthodes de contact.

Lorsque j'ai commencé à signer la bibliothèque de base (il peut s'agir de la même ou d'une autre clé de signature - tant que vous signez la bibliothèque de base), VS.Net a immédiatement pu fonctionner comme prévu.

Les réponses précédentes avec PublicKey ont fonctionné: (Visual Studio 2015: NÉCESSITÉ d’être sur une seule ligne, sinon il se plaint que la référence de l’assemblage est invalide ou ne peut pas être référencée. PublicKeyToken n’a pas fonctionné)

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

Merci à @Joe

Pour obtenir la clé publique de l'assemblage d'amis:

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

À l'intérieur d'une invite de commande du développeur (Démarrage > Programmes > Visual Studio 2015 > Outils Visual Studio > Invite de commande de développeur pour VS2015). Merci à @Ian G.

Bien que la touche finale qui a permis à mon travail de fonctionner après ce qui précède a été de signer le projet de bibliothèque de mon ami de la même manière que le projet de la bibliothèque à partager est signé. Comme il s'agissait d'une nouvelle bibliothèque de tests, elle n'était pas encore signée.

Vous devez générer une nouvelle clé publique complète pour l'assembly, puis spécifier l'attribut à l'assembly.

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

Suivez les instructions ci-dessous MSDN étapes pour générer une nouvelle clé publique complète pour l’assemblage à partir de visual studio.

Pour ajouter un élément Obtenir une clé publique d'assemblage au menu Outils

Dans Visual Studio, cliquez sur Outils externes dans le menu Outils.

Dans la boîte de dialogue Outils externes, cliquez sur Ajouter , puis entrez Obtenir la clé publique de l'ensemble dans la zone Titre.

Remplissez la zone de commande en accédant à sn.exe. Il est généralement installé à l'emplacement suivant: C: \ Program Files (x86) \ Microsoft SDK \ Windows \ v7.0a \ Bin \ x64 \ sn.exe .

Dans la zone Arguments, tapez ce qui suit (sensible à la casse): -Tp $ (TargetPath) . Cochez la case Utiliser la fenêtre de sortie.

Cliquez sur OK . La nouvelle commande est ajoutée au menu Outils.

Chaque fois que vous avez besoin du jeton de clé publique de l'assemblage que vous développez, cliquez sur la commande Obtenir l'assemblage de la clé publique dans le menu Outils. Le jeton de clé publique apparaît dans la fenêtre de sortie.

Une autre possibilité qu'il peut être difficile de dépister, dépend de la manière dont votre code est écrit.

  1. Vous appelez une méthode interne définie dans X à partir d'un autre assemblage Y
  2. La signature de la méthode utilise les types internes définis dans Z
  3. Vous devez ensuite ajouter [InternalsVisibleTo] dans X AND dans Z

Par exemple:

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

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

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

Si vous l'avez écrit comme ci-dessus, où vous ne faites pas référence à ZType directement dans Y, après avoir ajouté Y en tant qu'ami de X, vous risquez de ne pas savoir pourquoi votre code ne compile toujours pas.

L'erreur de compilation pourrait certainement être plus utile dans ce cas.

Ne s'applique que si vous souhaitez conserver les assemblys non signés comme assemblage non signé (et ne souhaitez pas le signer pour plusieurs raisons):

Il y a encore un autre point: si vous compilez votre bibliothèque de base à partir de VS.Net dans un répertoire local, cela peut fonctionner comme prévu.

BUT: dès que vous compilez votre bibliothèque de base sur un lecteur réseau, les stratégies de sécurité s'appliquent et l'assembly ne peut pas être chargé avec succès. Ceci provoque à nouveau l'échec de VS.NET ou du compilateur lors de la recherche de la correspondance PublicKey.

ENFIN, il est possible d'utiliser des assemblys non signés: https://msdn.microsoft.com/en-us/library/bb384966.aspx Vous devez vous assurer que LES DEUX ASSEMBLAGES NE SONT PAS SIGNES Et l'attribut Assembly ne doit pas contenir d'informations PublicKey:

<Assembly: InternalsVisibleTo("friend_unsigned_B")>

J'écris ceci par frustration. Assurez-vous que l'assembly auquel vous accordez l'accès est nommé comme vous le souhaitez.

J'ai renommé mon projet mais cela ne met pas automatiquement à jour le nom de l'assembly. Cliquez avec le bouton droit sur votre projet et cliquez sur Propriétés . Sous Application , assurez-vous que les noms d'assembly et l'espace de noms par défaut correspondent à vos attentes.

J'ai eu le même problème. Aucune des solutions n'a fonctionné.

Finalement, le problème était dû à la classe X implémentant explicitement l'interface Y, qui est interne.

la méthode X.InterfaceMethod n'était pas disponible, bien que je ne sache pas pourquoi.

La solution consistait à convertir (X sous la forme YourInterface) .InterfaceMethod dans la bibliothèque de tests, puis tout fonctionnait.

En remarque, si vous voulez obtenir facilement la clé publique sans avoir à utiliser sn et à comprendre ses options, vous pouvez télécharger le programme pratique ici . Il détermine non seulement la clé publique, mais crée également & "; L'assembly: InternalsVisibleTo ... &"; ligne prête à être copiée dans le presse-papiers et collée dans votre code.

Je viens de résoudre un problème similaire avec l'attribut InternalsVisibleTo. Tout semblait aller bien et je ne pouvais pas comprendre pourquoi la classe interne que je visais n'était toujours pas accessible.

Le changement de casse de la clé de majuscule à minuscule a résolu le problème.

Si vous avez plus d'un assemblage référencé, vérifiez que tous les assemblys nécessaires ont l'attribut InternalsVisibleTo. Parfois, ce n'est pas évident, et aucun message ne vous oblige à ajouter cet attribut dans un autre assemblage.

1- Signer le projet de test: Dans Visual Studio, accédez à la fenêtre des propriétés du projet de test et signez l'assemblage en cochant la case correspondante. case à cocher avec la même phrase dans l'onglet Signature .

2- Créez une clé publique pour le projet test: Ouvrez l'invite de commandes Visual Studio (par exemple, une invite de commande du développeur pour VS 2017). Accédez au dossier contenant le fichier .dll du projet de test . Créez une clé publique via sn.exe:

sn -Tp TestProject.dll

Notez que l'argument est -Tp, mais pas -tp.

3- Introduisez la clé publique dans le projet à tester: accédez au fichier AssemblyInfo.cs dans le projet à tester et ajoutez cette ligne avec la clé publique créée. à l'étape précédente:

[assembly: InternalsVisibleTo (&; & Quot TestProjectAssemblyName , PublicKey = 2066212d128683a85f31645c60719617ba512c0bfdba6791612ed56350368f6cc40a17b4942ff16cda9e760684658fa3f357c137a1005b04cb002400000480000094000000060200000024000052534131000400000100010065fe67a14eb30ffcdd99880e9d725f04e5c720dffc561b23e2953c34db8b7c5d4643f476408ad1b1e28d6bde7d64279b0f51bf0e60be2d383a6c497bf27307447506b746bd2075 quot;)]

N'oubliez pas de remplacer la clé publique ci-dessus par la vôtre.

4- Rendre la méthode privée interne: dans le projet à tester, définissez le modificateur d'accès de la méthode sur internal.

statique interne annule quelque chose () {...}

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top