Friend assemblies

Couple of weeks ago I started a refactoring task of a C# Class Library project. The Class Library exposed loads of public types and members. My first thought was to change the access modifiers of the types and members that did not make sense for the outside world. But changing the access modifiers from public to eg. internal raised a compilation problem for the unit tests that have been defined in a different project and that referred the public types and members.

In order to fix the problem with my unit tests it looked like only two options were available:

  • leave the access modifiers untouched (but the clients of my Class Library will see types and methods that they do not need, and also those types and members should not have been part of the public API)
  • move the unit tests to the Class Library that I started to refactor (in this way tests and production code will be contained in the same assembly and tests could refer internal-s also)
  • *** a third option came into view : Fried Assemblies

A friend assembly is an assembly that can access another assembly’s internal types and members (this feature has started to be available from C# 2 and .Net 2.0).

Let me demonstrate how to work with friend assemblies.

First lets set-up a small Visual Studio solution (I will use Visual Studio 2010). The solution consists of:

  • a Class Library named Source
  • a Console Application named Friend that will have a reference to Source

Now lets just define a public class inside Source project. This will contain a public method:


public class Operators
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}

Inside Friend project we will define the Program class that will contain a Main method:


public class Program
{
    public static void Main(string[] args)
    {
        var operators = new Operators();

        Console.WriteLine(operators.Add(1, 2));
    }
}

Friend project refers Source, so Friend will be able to access all public types and their public members defined in Source.
Everything compiles and runs just fine. But lets assume that we do not need to expose the int Add(int a, int b) method as public; this method has been defined for internal use in Source assembly, so we will make it internal:


public class Operators
{
    internal int Add(int a, int b)
    {
        return a + b;
    }
}

We would like to still be able to test the internal int Add(int a, int b) method from outside the current assembly (as we do in Friend assembly). In order to do so, we can declare in the AssemblyInfo.cs file (inside Source project) the set of friend assemblies that will be able to call the internals from Source:

We add in AssemblyInfo.cs the following line:


...
[assembly: InternalsVisibleTo("Friend")]
...

By adding [assembly: InternalsVisibleTo("Friend")] to AssemblyInfo.cs we say that code from Friend assembly will be able to work with internal types and members from Source.

Conclusion

Using Friend Assemblies could be an elegant solution to have good separation between production code and unit test code.

Still there might be some security issues but you can overcome them by signing the friend assembly and using its full public key in the AssemblyInfo.cs of the source assembly. We will discuss more related to this topic in a subsequent post so stay tuned. 🙂

Advertisements

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