Introduction
If you want to move a type from one assembly to another without disrupting callers that compiled against the old assembly, then you should use the TypeForwardedToAttribute
attribute.
Background
The scenario is you have an application which has a project which has the details of an employee like manager, clerk, and house-keeping, and you have successfully deployed the application, but some time down the line, it was realized that the HouseKeeping
class is best suited under the Vendor category which is in another project (DLL). We can make the changes in the code of Employee which is in another project (DLL) to the Vendor
class and just use the TypeForwardedToAttribute
to avoid re-building the application and re-deploying it. We just build the respective project and use the DLL, except the main hosting application, and the trick works.
Using the code
Step 1: Creating an assembly
The first step is to create an assembly that has the sample type named Employee
. The Employee class has several methods named Display
, DisplayClerk
, and DisplayHouseKeeping
, which display some information.
To create the assembly
- Create an empty solution named "TypeForwardedToAttribute_First" and add to it a "Class Library Project" named "Employee.cs".
Note: Please delete Class1.cs from the "TypeForwardedToAttribute_First" project if it is created automatically. We don't need it.
- Add a class named "
Employee
" to the "TypeForwardedToAttribute_First" project and modify its code as below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using TypeForwardedToAttribute_First;
namespace TypeForwardedToAttribute_First
{
public class HouseKeeping
{
public void DisplayHouseKeeping()
{
Console.WriteLine("HouseKeeping Class");
}
}
public class Manager : Employee
{
public void Display()
{
Console.WriteLine("Manager Class");
}
}
public class Clerk : Employee
{
public void DisplayClerk()
{
Console.WriteLine("Clerk Class");
}
}
public class Employee
{
static void Main(string[] args)
{
Console.WriteLine("Trainee Class Will be Moved");
}
public static void Display()
{
}
}
}
- Now you can build the TypeForwardedToAttribute_First project, which produces TypeForwardedToAttribute_First.dll in its output folder.
Step 2: Creating a host application
The next step is to create an application for hosting Employee
. Creating a "Console Application" is the simplest way which satisfies Employee hosting.
To create the host application
- Add a "Console Application" project named "TypeForwardedToAttribute" to the solution.
- Add a reference from the TypeForwardedToAttribute_First project to the TypeForwardedToAttribute project.
- Modify the
Program
class as below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TypeForwardedToAttribute_First;
namespace TypeForwardedToAttribute
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Please understand the Type Forwarding Concept");
Clerk objClerk = new Clerk();
Manager objManager = new Manager();
HouseKeeping objHouseKeeping = new HouseKeeping();
objClerk.DisplayClerk();
objManager.Display();
objHouseKeeping.DisplayHouseKeeping();
Employee.Display();
Console.ReadLine();
}
}
}
- Set the TypeForwardedToAttribute project as the "Startup Application" and run the solution. You will see that ExampleType presents itself like below:
Please understand the Type Forwarding Concept
Clerk Class
Manager Class
HouseKeeping Class
Step 3: Creating a new assembly
The next step is to create a new assembly which will be the destination of moving the HouseKeeping
type. Consider that you have deployed TypeForwardedToAttribute
to several users and now you need to update Employee
, i.e., removing the HouseKeeping
class from it, but you don't want to disrupt the deployed application. In this condition, you should create a new assembly and move the type to it. Then you should copy both assemblies to the deployed application folder.
To create the new assembly
- Add a "Class Library" named "TypeForwardedToAttribute_Second" to the solution.
Note: Please delete Class1.cs from the TypeForwardedToAttribute_Second project if it is created automatically. We don't need it.
- Add a class named "
Vendor
" to the TypeForwardedToAttribute_Second project and modify its code as below.
Very important note: By default, the added class will be in the TypeForwardedToAttribute_Second
namespace, but you must rename its namespace name to TypeForwardedToAttribute_First
because of the following rule.
Rule: The original type and the forwarded type must be in the same namespace.
Let's see the HouseKeeping
declaration in the TypeForwardedToAttribute_Second project.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TypeForwardedToAttribute_First
{
public class HouseKeeping
{
public void DisplayHouseKeeping()
{
Console.WriteLine("HouseKeeping Class from Vendor");
}
}
public class Vendor
{
static void Main(string[] args)
{
}
}
}
Step 4: Moving the type
The next step is to move HouseKeeping
to its destination: TypeForwardedToAttribute_Second.
To move the type
- Add a reference from the TypeForwardedToAttribute_Second project to the TypeForwardedToAttribute_First project.
- Comment the
HouseKeeping
declaration in the TypeForwardedToAttribute_First project and add a TypeForwardedToAttribute
attribute instead, as below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using TypeForwardedToAttribute_First;
[assembly: TypeForwardedTo(typeof(HouseKeeping))]
namespace TypeForwardedToAttribute_First
{
public class Manager : Employee
{
public void Display()
{
Console.WriteLine("Manager Class");
}
}
public class Clerk : Employee
{
public void DisplayClerk()
{
Console.WriteLine("Clerk Class");
}
}
public class Employee
{
static void Main(string[] args)
{
Console.WriteLine("Trainee Class Will be Moved");
}
public static void Display()
{
}
}
}
Very important note: Don't build the TypeForwardedToAttribute project again here, else you will get a compiler error because of the following rule:
Rule: Forwarded types can't be referenced.
Applying the moved type to the host
The final step is to apply the new type to the deployed host.
To apply the moved type
- Build the TypeForwardedToAttribute_Second project first and then build the TypeForwardedToAttribute_First project.
- Copy and replace TypeForwardedToAttribute_First.dll beside TypeForwardedToAttribute.exe.
- Copy TypeForwardedToAttribute_Second.dll beside TypeForwardedToAttribute.exe too.
- Double click TypeForwardedToAttribute.exe. You will see that
HouseKeeping
presents itself like:
Please understand the Type Forwarding Concept
Clerk Class
Manager Class
HouseKeeping Class from Vendor
As you can see, it tell us that it is from type ForwardedToAttribute_Second
. Yes, the job is done.
The Limitation
The .NET Framework version 2.0 does not allow type forwarding from assemblies written in Visual Basic. However, a Visual Basic application can consume forwarded types if it uses assemblies coded in C# or C++.