Friend of C#

In the world of Test Driven Development (TDD) the revivial of the need for a “friend” access modifier is becoming more and more apparent. Typically, you want to have all your tests in a different assembly (project) to your actual code – for cleanness, security and responsibility reasons. However, this presents a dilema – you want to be able to write test cases for all those internal methods. By default, “internal” methods are only exposed to other classes in the same project.

So, the typical approach is to make the methods “public” and either (forget to) change them at go live, or have a cluttered API full of methods that are not meant to be called directly. The same goes for variables. C++ had the ever useful “friend” language embelishment to handle these types of scenarios, but C# is caught lacking.

Fortunately, as of .Net 2.0, there is the wonderfully named “InternalsVisibleToAttribute”. This is an assembly wide (read: AssemblyInfo.cs) attribute that states that all items with the “internal” modifier are accessable to the assemblies identified with this attribute. So how do you identify them? Easy: open up the AssemblyInfo.cs of the assembly you want to expose the internals of (hmm, that almost sounds, well, awkward), and add the following line:

[assembly: InternalsVisibleToAttribute(“TestListGenerator.Tests”)]

Where TestListGenerator.Tests is the name of the library that you want to have to access to this assemblies internals. Of course, you’ll probably want to move to the world of strong naming to prevent people from getting to friendly with your internals. In which case, after you’ve signed all your projects (it’s easy: right click Project > Properties > Signing > new) you need to get the _full_ public key of the calling project. You can do this with Visual Studio’s sn.exe (included in the path when you use the VS Command Prompt):

sn.exe -T TestListGenerator.Tests.dll

NB: the case of the T matters. This will give you something like:

Public key is
0x0024000004800000940000000602000000240000525341310004000001000100adfedd2329a0f8
3e057f0b14e47f02ec865e542c2dcca6349177fe3530edd5080276c48c6d02fa0a6f67738cc1a0
793be3322cf17b8995acc15055c00fa61b67a203c7eb2516922810ff0b17cd2e08492bdcafc4a9
23e6fff4caba672a4c2d0d0f5cac9aea95c3dce3717bb733d852c387f5f025c42c14ec8d759f7e
b13689be

Strip out the 0x, and copy the rest of the string. Update your InternalsVisibleTo attribute to be:

[assembly: InternalsVisibleTo(“TestListGenerator.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100adfedd2329a0f8
3e057f0b14e47f02ec865e542c2dcca6349177fe3530edd5080276c48c6d02fa0a6f67738cc1a0
793be3322cf17b8995acc15055c00fa61b67a203c7eb2516922810ff0b17cd2e08492bdcafc4a9
23e6fff4caba672a4c2d0d0f5cac9aea95c3dce3717bb733d852c387f5f025c42c14ec8d759f7e
b13689be”]

Warning: If you use the public key token instead of the full public key, you’ll end up with an error like the following:

warning CS1700: Assembly reference ‘TestListGenerator.Tests, PublicKey=32ab4ba45e0a69a1’ is invalid and cannot be resolved

Advertisements
Post a comment or leave a trackback: Trackback URL.

Comments

  • Chandru  On February 24, 2010 at 12:50 am

    its sn.exe -Tp TestListGenerator.Tests.dll

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: