C# and Friend Assemblies Made Easy

! Warning: this post hasn't been updated in over three years and so may contain out of date information.

friendassembly_small.pngIf you are familiar with C++, you’ll know about “friend classes” within that language. If you are not familiar with them, they are a neat way of exposing otherwise private methods to trusted classes. Class A has a bunch of private members, that are obviously hidden to other classes, but there is a problem with this model. Class B is a unit test class that tests class A. Because it is doing unit tests, it needs to delve deep inside class A to check what is going on. By making class B a friend of class A, the former is then granted access to the latter’s inner workings.

So what does this have to do with C#? Well C# partially fixed this with the “internal” keyword. Internal members of a class are visible to other classes within the same assembly, but are effectively private as far as classes outside the assembly are concerned. Internal members are very different from protected ones by the way. In the latter case, they are only visible to subclasses (whether in the same assembly or not). However, largely due to a limitation with Visual Studio, internal members used not to be the full answer to the needs of unit testing. The C# compiler supports compiling multiple projects into one assembly, but Visual Studio has a strict one to one project/ assembly mapping. So unit test classes used to have to reside within the same project as the product code (which wasn’t practical if the project’s assembly was a executable, rather than a dll.) The other alternative was to expose all the members that the unit test classes needed to access by making them public.

I talk in the past tense in the previous paragraph as this problem was fixed with the release of C# 2.0. This introduced the idea of Friend Assemblies. To explain, let’s go back to our class A and B. Class A resides in assembly A.dll. Class B resides in assembly B.dll. Normally class B would have no access to the internals of class A. Add the “InternalsVisibleTo” attribute to class A though, specifying B.dll as the trusted assembly and now class B can access those internals. Further, unlike with C++ and friend classes, private members in class A remain private; only internals are exposed via this method.

If both A.dll and B.dll are unsigned, the extra code is just:

which is a pretty neat solution.

Things get really messy though the moment signed assemblies are used. The reason is that one must put the public key (not the nice short token, the full-blown humongous key) in the attribute. So it becomes something like:

(I’ve wrapped the public key across many lines for clarity. In reality, it must be on one line)

The whole horrible nastiness of the matter doesn’t stop there though. To get that public key, one must find the sn.exe tool, plough through its dozens of obscure options, and then run the right one against the required assembly (or run a sequence of two even more obscure commands against the original key file). Then one can cut and paste the output of the command into the attribute in Visual Studio. This is what we in Britain politely term a “complete faff”.

Having banged my head against the wall performing this operation recently, I decided that a simply little utility was required to do all the work. So I wrote an app called FriendAssembly, which I’m sharing here.

FriendAssembly is a basic windows application as shown in the screen-shot below:

friendassembly.png

The application is simple to use: run it, use the file selector dialog to point at the required signed assembly/ snk file and then hit the copy to clipboard button. Next switch to Visual Studio, put the cursor at the start of the word “class” and hit ctrl-V. All done.

You can download the binary installer here. It is an MSI file that requires the .NET framework version 2. I’ve tested it on WIndows XP and Vista. I’ve no idea if it’ll work with other versions of windows.

Alternatively the source files (as a Visual Studio 2005 solution) are available as a zip file here.

The official documentation on friend assemblies is available here. It’s not very good though in my view.

4 thoughts on “C# and Friend Assemblies Made Easy

  1. Thanks so much for this tip: “I’ve wrapped the public key across many lines for clarity. In reality, it must be on one line.”

    I had concatenated the string over multiple lines for readability, and it wasn’t working. It really, really, really wants to be on one line. You saved me some work.

    Looks like your tool is cool, too. It is indeed a nuisance extracting the public key — almost like MS got tired and ran out of steam before they finished implementing the whole strong naming / code signing regimen.

  2. Thanks for sharing this. However when I try to use the tool I get a message saying that sn.exe does not appear to be installed on this machine. I’ve (1) placed the location of sn.exe in my Path environment variable and (2) reinstalled the application to the same folder location as sn.exe. But still have no luck. I’m running Windows 7 any suggestions on how I can FriendAssembly to work?

  3. Denise, a bit late but here is the answer to your question. The tool is expecting to find sn.exe in one of the following locations:
    C:\Program Files\Microsoft SDKs\windows\v6.0a\bin
    C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin

    You could either download the source and rebuild it pointing at the location of you sn.exe, or create one of those directories and copy sn.exe there.

Comments are closed.