This article could be entitled "every day I love you more and more", sung in the jaunty manner of the Kaiser Chiefs song,
however I do mean more and not less. Let me explain.
For years (well, about 5 now, give or take a month or two) I've been using .NET, and most of that time I've been heavily
into attributes. Not the XML ones I hasten to add - don't get me going, but instead the ones you get in .NET. One of my first
talks about .NET was on attributes, as was a chapter in one of the books I helped with. I love 'em. One of my other
favourite things is unit testing (I know, pretty strange for a developer type, but it's true). I also *love* documenting
my code too.
Anyhow, I digress. One of the problems I've always had with unit testing is that the tests need to live in a separate
assembly, and so anything under test has to be publicly visible outside the assembly. Not great.
Enter the [InternalsVisibleTo()] attribute. This little beauty will allow
you to separate your unit tests from your code, but make it possible to call internals from another assembly. Cool!.
|
using System;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo ( "UnitTests" ) ]
|
That's all there is to it (well, nearly). When you compile the main assembly, we pickle (yes, that's the right word!) this
attribute into it. Then, when you try to compile your unit tests, the compiler is clever enough to look for this attribute and
emit the appropriate stuff so that you can then call you internal classes/methods. Obviously the above is a little lacking, in
that I've only specified "UnitTests" as the name of the assembly. Typically you would use not only the name but also the
public key token of that assembly. The text used by the attribute is an assembly name, so you can add in culture etc to the string
too.
The [InternalsVisibleTo()] attribute also allows you to use it multiple times,
so you could have a list of assemblies that can call your internal methods.
Now, this isn't a suggestion that you mark all your public methods internal, nor is it a suggestion that you should mark
all privates as internals - use this where it makes sense, but sparingly.
For more information, see the Friend Assemblies
topic on MSDN.