InternalsVisibleTo attribute isn't working

后端 未结 19 2414
眼角桃花
眼角桃花 2020-11-27 13:51

I am trying to use the InternalsVisibleTo assembly attribute to make my internal classes in a .NET class library visible to my unit test project. For some reas

相关标签:
19条回答
  • 2020-11-27 13:57

    You are required to generate an new full public key for the assembly and then specify the attribute to assembly.

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

    Follow the below MSDN steps to generate new full public key for the assembly from visual studio.

    To add a Get Assembly Public Key item to the Tools menu

    In Visual Studio, click External Tools on the Tools menu.

    In the External Tools dialog box, click Add and enter Get Assembly Public Key in the Title box.

    Fill the Command box by browsing to sn.exe. It is typically installed at the following location: C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0a\Bin\x64\sn.exe.

    In the Arguments box, type the following (case sensitive): -Tp $(TargetPath). Select the Use Output window check box.

    Click OK. The new command is added to the Tools menu.

    Whenever you need the Public Key Token of the assembly you are developing, click the Get Assembly Public Key command on the Tools menu, and the public key token appears in the Output window.

    0 讨论(0)
  • 2020-11-27 13:57

    Another possibility that may be tricky to track down, depending on how your code is written.

    1. You're invoking an internal method defined in X from another assembly Y
    2. The method signature uses internal types defined in Z
    3. You then have to add [InternalsVisibleTo] in X AND in Z

    For example:

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

    If you have it written like above, where you're not referring to ZType directly in Y, after having added Y as a friend of X, you may be mystified why your code still doesn't compile.

    The compilation error could definitely be more helpful in this case.

    0 讨论(0)
  • 2020-11-27 13:59

    If your assemblies aren't signed, but you are still getting the same error, check your AssemblyInfo.cs file for either of the following lines:

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

    The properties tab will still show your assembly as unsigned if either (or both) of these lines are present, but the InternalsVisibleTo attribute treats an assembly with these lines as strongly signed. Simply delete (or comment out) these lines, and it should work fine for you.

    0 讨论(0)
  • 2020-11-27 14:02

    Here's a macro I use to quickly generate this attribute. Its a bit hacky, but it works. On my machine. When the latest signed binary is in /bin/debug. Etc equivocation etc. Anyhow, you can see how it gets the key, so that'll give you a hint. Fix/improve as your time permits.

    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
    
    0 讨论(0)
  • 2020-11-27 14:02

    In my case using VS.Net 2015, I needed to sign BOTH assemblies (if at least 1 assembly shall be signed or you want to reference on the public key of your assembly).

    My project didn't use signing at all. So I started adding a sign key to my test library and useing the InternalsVisibleTo-Attribute at my project's base library. But VS.Net always explained it couldn't access the friend methods.

    When I started to sign the base library (it can be the same or another sign key - as long as you do sign the base library), VS.Net was immediately able to work as expected.

    0 讨论(0)
  • 2020-11-27 14:03

    As a side note, if you want to easily get the public key without having to use sn and figure out its options you can download the handy program here. It not only determines the public key but also creates the "assembly: InternalsVisibleTo..." line ready to be copied to the clipboard and pasted into your code.

    0 讨论(0)
提交回复
热议问题