Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Friend Assemblies in C#

I'm trying to create some 'friend assemblies' using the [InternalsVisibleTo()] attribute, but I can't seem to get it working. I've followed Microsoft's instructions for creating signed friend assemblies and I can't see where I'm going wrong. So I'll detail my steps here and hopefully someone can spot my deliberate mistake...?

Create a strong name key and extract the public key, thus:

sn -k StrongNameKey
sn -p public.pk
sn -tp public.pk

Add the strong name key to each project and enable signing.

Create a project called Internals and a class with an internal property:

namespace Internals
{
    internal class ClassWithInternals
    {
        internal string Message { get; set; }
        public ClassWithInternals(string m)
        {
            Message = m;
        }
    }
}

Create another project called TestInternalsVisibleTo:

namespace TestInternalsVisibleTo
{
    using Internals;

    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            var c = new Internals.ClassWithInternals("Test");
            Console.WriteLine(c.Message);
        }
    }
}

Edit the AssemblyInfo.cs file for the Internals project, and add teh necessary attribute:

[assembly: AssemblyTitle("AssemblyWithInternals")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("Internals")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("41c590dc-f555-48bc-8a94-10c0e7adfd9b")]

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

[assembly: InternalsVisibleTo("TestInternalsVisibleTo PublicKey=002400000480000094000000060200000024000052534131000400000100010087953126637ab27cb375fa917c35b23502c2994bb860cc2582d39912b73740d6b56912c169e4a702bedb471a859a33acbc8b79e1f103667e5075ad17dffda58988ceaf764613bd56fc8f909f43a1b177172bc4143c96cf987274873626abb650550977dcad1bb9bfa255056bb8d0a2ec5d35d6f8cb0a6065ec0639550c2334b9")]

And finally... build!

I get the following errors:

error CS0122: 'Internals.ClassWithInternals' is inaccessible due to its protection level
error CS1729: 'Internals.ClassWithInternals' does not contain a constructor that takes 1 arguments error CS1061: 'Internals.ClassWithInternals' does not contain a definition for 'Message' and no extension method 'Message' accepting a first argument of type 'Internals.ClassWithInternals' could be found (are you missing a using directive or an assembly reference?)

Basically, it's as if I had not used the InternalsVisibleTo attrbute. Now, I'm not going to fall into the trap of blaming the tools, so what's up here? Anyone?

like image 363
Tim Long Avatar asked Apr 30 '10 17:04

Tim Long


1 Answers

You're missing a comma after the assembly name in your InternalsVisibleTo attribute.

It should be:

[assembly: InternalsVisibleTo("TestInternalsVisibleTo, PublicKey=....];

Assembly references can be finicky, and unfortunately the compiler does not attempt to verify them when they appear inside of attributes as strings. If you mispell the assembly reference or provide an invalid key - everything will compile - but just not work.

like image 163
LBushkin Avatar answered Oct 28 '22 15:10

LBushkin