Geeks With Blogs
Chris Falter .NET Design and Best Practices

I work for an ISV, and we have to be very cautious about the code that we declare with public scope.  If it's public, a customer can treat it as an API, which might not always be a good idea if the code is really just doing some internal task in a way that could easily change as we improve our software.  In other words, not all that is public should be an API.

So what do you do if you need to share code across assembly boundaries?  Recently I was writing some unit tests for a class, and the tests needed access to a class method in order to imitate (and test) its behavior.  Of course this method was private--of course!--so it appeared that I had to choose between 2 very unpalatable options:

  1. Give the method public scope, which would make it visible to all our customers' implementations.  Essentially, this option would make the method part of our API.  Not happening.
  2. Copy the 20 lines of code from the method, paste it into my new class, and supplicate the dark spirits of bad software design to supernaturally prevent the method from ever being modified.  But how could I perform the ritual without an eye of newt and toe of frog?*

But appearances can be deceiving.  It turns out that the InternalsVisibleToAttribute, introduced by Microsoft in .NET 2.0, solves the problem quite neatly.  Using this attribute, you can designate one or more friend assemblies that will be allowed access to classes, methods and properties in the target assembly that have friend scope, while all other code--including customer code--is denied access.

Using the attribute is a piece of cake:

  1. Mark any classes/methods/properties that need to be visible to other assemblies with "Friend" scope.
  2. Import the System.Runtime.CompilerServices namespace into your assembly's AssemblyInfo.vb file.

    Imports System.Runtime.InteropServices

  3. In AssemblyInfo.vb, mark the assembly with the InternalsVisibleToAttribute for each friend assembly that should have access to the friend scope.

    <Assembly: InternalsVisibleTo("MySystem.Assembly1")>
    <Assembly: InternalsVisibleTo("MySystem.Assembly2")>

If you are working in C#, you will make your changes in the AssemblyInfo.cs file for the assembly that contains the code to be re-used, and you will use "using" instead of "Imports."

So I could have my cake (re-use of existing code) and shield it from inappropriate eyes at the same time.  While this technique is obviously useful for writing tests, it can be applied anywhere that code needs to be shared between your system's assemblies without exposing it customers as part of an API. 

 

* Not to mention the wool of bat and tongue of dog.

 

Posted on Sunday, March 29, 2009 2:44 PM Coding Practices and Design Patterns , Testing & Debugging | Back to top


Comments on this post: How to Reuse Code Without Creating an Implicit API

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Chris Falter | Powered by: GeeksWithBlogs.net