65.9K
CodeProject is changing. Read more.
Home

Limiting the Accessibility- Another Way of Friend Assemblies

starIconstarIconstarIconstarIconstarIcon

5.00/5 (4 votes)

Mar 5, 2012

CPOL

3 min read

viewsIcon

12571

How to limit accessibility - another way of friend assemblies

In my last post, I discussed how to access internal class of one assembly in another assembly and that is easily achieved with the help of a C# feature called Friend Assemblies. It allows us to call the internal methods of another assembly. It is very much required on several occasions like the one I discussed in my last post, Unit Testing. It is often required to test the internal classes of the assembly in another project of Unit testing and it can be done easily via Friend Assembly.

To see my last post, please take a look at How to access internal class of one assembly to other assembly.

But in some other scenarios, Friend assemblies solution may not work. Like if you have two assemblies and one assembly accesses other assembly using Friend assembly. It’ll be fine as long as both assemblies are compatible and shipped at the same point of time. And if it does not happen on a regular basis or in every release/update of assembly, this may be hazardous.

To avoid it, we should implement it in another way. Here, we declare the method as public but will limit its accessibility to some specific assembly. It can be achieved by using LinkCommand with StrongNameIdentityPermission.

What is LinkCommand?

LinkCommand is a SecurityCommand which comes in the umbrella of Code Access Security(CAS). That allows you limit the accessibility of an assembly.

This can be applied at assembly, class and method level as well.

Here, I’ll show you how you can allow only the assembly that wants to call the method that will be able to execute it.
For this, we need to follow the steps given below:

  1. Create a project with a method that needs to be called from another application
  2. Create another project that will be calling the method
  3. Sign the second assembly/project
  4. Get the public key.
  5. Apply the StrongName attribute to the First assembly’s method with the public key of the second assembly
  6. Now call the method from second assembly

So let's go step by step:

  1. Let’s create a First Project: Create a class library, say named LinkDemandSample and it has a class named SampleClass. I have also created a method named SayHello. The class would look like follows:
        public class SampleClass
        {
            public string SayHello(string name)
            {
                return "Hello " + name;
            }
        }    
  2. Create a second project (say create a console application named TestLinkDemand) that calls the method SayHello.

    Currently, SayHello method can be called to any assembly because it is public and it has not been limited for accessibility.

  3. Now we need to sign the second project that we’ll do so using sn.exe.

    First, we need to create public/private key pair. This will be generated in .snk file. Use the below command

    sn-k TestLinkDemand.snk

    Then, apply this file to the assembly. Go to assembly info and add the following line:

    [assembly: AssemblyKeyFile(@'..\..\TestLinkDemand.snk')]

    Or you can right click on project in solution explorer and click properties.

  4. Now your assembly is signed but we need to get the public key because it is required for the SecurityCommand action.

    Use the following command which extracts the public key in a new file.

    sn -p TestLinkDemand.snk TestLinkDemand.public

    It will generate the public key in a new file TestLinkDemand.public but it is not readable because it is in
    binary format. So to read the public command, use the following command:

    sn -tp TestLinkDemand.public

  5. Now we need to apply the StrongNameIdentityPermission attribute to the method as:
       public class SampleClass
        {
            [StrongNameIdentityPermission(SecurityAction.LinkDemand, PublicKey =
                "00240000048000009400000006020000002400005253413100040000010001005f47ddff483a87" +
                "7b26c7fe31b029be4f6d6deeb149a5f732c548507fbce2bafa8bd7a6c04e078a5b7e069fad0222" +
                "27b7550fe15914fa03f35ef0a02f5c61f6a048c3e36ce304ebc407e1fb8962c56e27d4f0f691a2" +
                "05731e7c15b1565cdfcef03c9191e688834ac6d9f8e0a1a2651b9f5e291a68daea5475d233539e" +
                "cb9404a3")]
            public string SayHello(string name)
            {
                return "Hello " + name;
            }
        }    
  6. Now this can be called only from the second application. And if it is called by any other assembly, the following exception will be thrown:

Hope you all have liked this.

Happy coding!
Brij