
If 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:
|
[assembly:InternalsVisibleTo("B")] class A { .... |
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:
|
[assembly:InternalsVisibleTo("B, PublicKey=0024000004800000940000000602000 000240000525341310004000001000100031d7b6f3ab c16c7de526fd67ec2926fe68ed2f9901afbc5f1b6b42 8bf6cd9086021a0b38b76bc340dc6ab27b65e4a593fa 0e60689ac98dd71a12248ca025751d135df7b98c5f9d 09172f7b62dabdd302b2a1ae688731ff3fc7a6ab9e8c f39fb73c60667e1b071ef7da5838dc009ae0119a9cbf f2c581fc0f2d966b7114b2c4")] class A { .... |
(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.
Continue reading “C# and Friend Assemblies Made Easy” →