TypeForwardedTo Attribute: Forward a Type to a Different Assembly

Introduction

In .NET, one often refers to other assemblies that contain specific modules that you can use in your application. Say, you reference a DLL that contains some classes that you will use in your application. Suppose the application is deployed. Now, suppose you want to move one class of the DLL to another assembly. What can you do in this situation with old coding methodoligies? The old methodologies say,

  • Remove the class from the existing DLL.
  • Create another DLL (assembly) using that class.
  • Recompile both the DLLs.
  • From your application, add a reference to the new DLL.
  • Recompile the application.
  • Re-deploy the whole thing.

Wouldn't it be nice to leave the deployed application untouched, and make whatever changes are needed in the DLLs? Obviously, that would be nicer. That's where the TypeForwardedTo attribute comes into the scene. By using this, you can move your necessary classes out to a new assembly. Now, when your application looks for the class in the old DLL, the old DLL tells your application (the JIT compiler—to be precise), "Well, the person (class) who lived here has moved to another location; here is the address." It gives in the address, your application follows the address, there it finds the class, and things go on as is.

So, it's time to get inside the new idea.

Your First DLL

Create a new Windows Class Library project. Name it 'Library1'. The only class it has is 'Class1'. Now, following is the code of 'Class1'.

using System;
using System.Collections.Generic;
using System.Text;

namespace MyNameSpace
{
   public class MyClass
   {
      public int Calculate(int x, int y)
      {
         return x + y;
      }
   }

   public class MyResidentClassInLib1
   {
      public float CalculateRadius(float Radius)
      {
         return (float)(2 * Radius * 3.141592654);
      }
   }
}

This is your very neat and clean DLL that contains a class inside a namespace, and the class has two methods in it—one calculates the sum of the parameters, and the other calculates the radius using the parameter.

Choose Release Build, compile the code, and you have Library1.dll in the Release folder. (Of course, you can have a Debug Build also.)

Your Application

Start a new project of Windows Application type. Create the project in a different directory. This will be your only application form.

Simple. It just has two buttons on it. Clicking the buttons will refer two classes in a DLL that you have just created. First, refer to the DLL that you just created. From the Reference pane, add a reference to the new DLL. After successfully refering to the DLL, your solution explorer looks like the following:

Now, open Form1 in design mode and double-click the Calculate button. This will open the default click event handler for the Calculate button. Add the following code in the Click event handler.

private void btnCalculate_Click(object sender, EventArgs e)
{
   MyNameSpace.MyClass TestClass = new MyNameSpace.MyClass();
   MessageBox.Show(TestClass.Calculate(10, 20).ToString());
}

What is going on here? You referred to a MyClass type that resides in MyNameSpace and instantiated an object of the type. Then, you just called a method of the class. Please remember, MyNameSpace and MyClass are in the DLL that you just added.

Similarly, in the Click event handler of the other button of the form, you have the following code:

private void btnCalculateRadius_Click(object sender, EventArgs e)
{
   MyNameSpace.MyResidentClassInLib1 TestClass2 =
      new MyNameSpace.MyResidentClassInLib1();
   MessageBox.Show(TestClass2.CalculateRadius(200).ToString());
}

Thus, one button calculates a sum, and the other button calculates a radius using two mathematical methods that are shipped in a DLL.

Now choose Release Build, compile the code, and you have your released executable file MyApplication in the Release folder. Please look inside the Release folder, and you will find Library1.dll there. As you might know, it is a mechanism of .NET to create a copy of any referenced DLL in the same location of the executable.

Run the application and click the Calculate button. The output will be as follows:

Now, click the Calculate Radius button. The output will be as follows:

Now that you have a full-fledged application, say you have deployed it. At a future date, you felt the need to move one type from the DLL to another assembly (DLL, in this case). Here comes what you want to do with the TypeForwardedTo attribute. You will create another assembly (DLL) and move the class to the new assembly. Then, you have to compile the new DLL and add a reference to it from the previous DLL. Then, you will add a TypeForwardedTo attribute in the previous DLL to mean a specified type is forwarded to some other assembly. Then, you have to recompile the old DLL and, as a result, you will have two DLLs in the release folder of the previous DLL. Now, you just have to place both the DLLs in the root of the deployed application (or wherever the old DLL is).

TypeForwardedTo Attribute: Forward a Type to a Different Assembly

Forwarding the Type

Create another new Windows Class Library project. Name it 'Library2'. The only class it has is 'Class1'. Now, following is the code of 'Class1'.

using System;
using System.Collections.Generic;

namespace MyNameSpace
{
   public class MyClass
   {
      public int Calculate(int x, int y)
      {
         return x * y;
      }
   }
}

Note that the names of the namespace and the class (that is being forwarded) are same as in the old DLL. The functionality would also be the same, but because you want to show that the Calculate method will be called from the new DLL, you changed the functionality to a multiplication of the parameters (in the old DLL, it was an add operation).

Choose Release Build, compile the code, and you have Library1.dll in the Release folder.

The Old DLL

Open the old DLL project. Add a reference to the new DLL from the old DLL. So, the solution explorer looks like the following:

[Reference2.jpg]

Now, comment out the class that is being forwarded. So, your code in the old DLL is as follows:

using System;
using System.Collections.Generic;
using System.Text;

namespace MyNameSpace
{
   //public class MyClass
   //{
   //   public int Calculate(int x, int y)
   //   {
   //      return x + y;
   //   }
   //}

   public class MyResidentClassInLib1
   {
      public float CalculateRadius(float Radius)
      {
         return (float)(2 * Radius * 3.141592654);
      }
   }
}

Open the AssemblyInfo.cs file and add the following line right after the assembly directives.

[assembly: TypeForwardedTo(typeof(MyNameSpace.MyClass))]

That is, you just added one more directive in the assembly information file. Your assembly information file now has the following code:

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through
// the following set of attributes. Change these attribute values
// to modify the information associated with an assembly.
[assembly: AssemblyTitle("Library1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Dohatec New Media")]
[assembly: AssemblyProduct("Library1")]
[assembly: AssemblyCopyright("Copyright B) Dohatec New Media 2007")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: TypeForwardedTo(typeof(MyNameSpace.MyClass))]

// Setting ComVisible to false makes the types in this assembly
// not visible to COM components.  If you need to access a type in
// this assembly from COM, set the ComVisible attribute to true on
// that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project
// is exposed to COM
[assembly: Guid("4d9623c5-9fbf-4053-b34b-9b1827392f34")]

// Version information for an assembly consists of the following
// four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Revision
// and Build Numbers by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Choose Release Build, compile the code, and you have Library1.dll in the Release folder. This is a new build and, in the Release folder, you will find Library1.dll as well as Library2.dll. Simply copy the two DLLs and paste in the root of the deployed main application program.

Now, run the application and click on the Calculate button. The output will be as follows:

[CalculateNew.jpg]

See, the method and class from the new DLL are called from the application, even though the application doesn't even have the simplest information that many things have changed out there. Now, click the Calculate Radius button, and the output will be as follows:

[RadiusOldNew.jpg]

The class and method from the old DLL are called here. And, the output is same as before.

Summary

You now have an application that instantiates two classes and uses them when needed. The classes are residing in a DLL. Later, if there is an urge to pull out one class and put it in another assembly, then TepeForwardedTo attribute comes in to manage the whole thing without a single touch in the main application code. You just have to hide the old class from the old DLL, create another DLL and put the class there, add a reference from the old DLL to the new DLL, add a TypeForwardedTo directive in the assembly information file, and add both DLLs in the root of the main application.

Please note that the body of the method need not change. You have changed it to a multiplication just to prove that the class is instantiated from the new DLL. Also, note that the name of the namespace, the class, and the method should remain the same as the old DLL. What matters is that you are shifting a type to a new assembly and want your application to call the type from the new assembly. You want this to happen without a single modification in the application code. That is what the TypeForwardedTo attribute is intended to do.



About the Author

Mehedi Shams

Graduated in CSE from Khulna University, Bangladesh.
Software Engineer in professional life.
mehedishams@gmail.com

Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • New IT trends to support worker mobility — such as VDI and BYOD — are quickly gaining interest and adoption. But just as with any new trend, there are concerns and pitfalls to avoid.  Download this paper to learn the most important considerations to keep in mind for your VDI project.

  • IBM Worklight is a mobile application development platform that lets you extend your business to mobile devices. It is designed to provide an open, comprehensive platform to build, run and manage HTML5, hybrid and native mobile apps.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds