Forwarding a type from one assembly to another: TypeForwardedToAttribute





5.00/5 (7 votes)
Walkthrough: Forwarding a type from one assembly to another by using the TypeForwardedToAttribute attribute.
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".
- Add a class named "
Employee
" to the "TypeForwardedToAttribute_First" project and modify its code as below: - Now you can build the TypeForwardedToAttribute_First project, which produces TypeForwardedToAttribute_First.dll in its output folder.
Note: Please delete Class1.cs from the "TypeForwardedToAttribute_First" project if it is created automatically. We don't need it.
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");
}
}
/// <summary>
/// This is a Manager Class
/// </summary>
public class Manager : Employee
{
/// <summary>
/// This Method will display details about Manager
/// </summary>
public void Display()
{
Console.WriteLine("Manager Class");
}
}
public class Clerk : Employee
{
/// <summary>
/// This Method will display details about Clerk
/// </summary>
public void DisplayClerk()
{
Console.WriteLine("Clerk Class");
}
}
public class Employee
{
static void Main(string[] args)
{
Console.WriteLine("Trainee Class Will be Moved");
}
/// <summary>
/// This is a main Method will display details about Manager,Clerk,Trainee
/// </summary>
public static void Display()
{
}
}
}
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: - Set the TypeForwardedToAttribute project as the "Startup Application" and run the solution. You will see that ExampleType presents itself like below:
/*The purpose of this Source code is to make
* the Concept of TypeForwardedToAttribute crystal clear
* SHORT DESCRIPTION -The scenario is you have an application
* which have a Project which have 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 ralized that the HouseKeeping Class is BestSuited
* Under Vendor Category which is in another project(dll)
* then we can make the changes in the Code of Employeee
* which is in another project(dll) to the Vendor Class
* and just use the TypeForwardedToAttribute to avoid
* the re-building of an applicatioon and re-deploying it
* we just build the respective project and use there dll except
* the main hosting application and the trick works
* Thumb Rule-Only use is when you have some legacy application
* (no source available, or cannot recompile for any other reason)
* referencing the type T1 originally located in A1 and for whatever
* reason you need to move the type out from that
* assembly.Then you can use the concept of TypeForwardedToAttribute
* and you'll have your type happily moved out
* of A1 to A2, legacy binary still referencing the A1,
* but using type T1 from A2.At least that's the reason for
* the attribute from my understanding
*
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TypeForwardedToAttribute_First;
/* VERY IMPORTANT NOTE: Don't build the TypeForwardedToAttribute
* project again here elsewhere you will
* get a compiler error because of following rule.
* RULE: Forwarded types can't be referenced.*/
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();
}
}
}
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.
- Add a class named "
Vendor
" to the TypeForwardedToAttribute_Second project and modify its code as below.
Note: Please delete Class1.cs from the TypeForwardedToAttribute_Second project if it is created automatically. We don't need it.
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;
/*The name space is modified from TypeForwardedToAttribute_First
*to TypeForwardedToAttribute_Second as this is must for TypeForwarding
*to attribute as the Rule says:"The original type and the forwarded type
*must be in a same namespace."*/
namespace TypeForwardedToAttribute_First
{
public class HouseKeeping
{
public void DisplayHouseKeeping()
{
Console.WriteLine("HouseKeeping Class from Vendor");
}
}
/// <summary>
/// Main Vendor Class
/// </summary>
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 aTypeForwardedToAttribute
attribute instead, as below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
using TypeForwardedToAttribute_First;
/*Need to refer using System.Runtime.CompilerServices*/
[assembly: TypeForwardedTo(typeof(HouseKeeping))]
namespace TypeForwardedToAttribute_First
{
/* This HouseKeeping class is moved to TypeForwardedToAttribute_Second*/
//public class HouseKeeping
//{
// public void DisplayHouseKeeping()
// {
// Console.WriteLine("HouseKeeping Class");
// }
//}
/// <summary>
/// This is a Manager Class
/// </summary>
public class Manager : Employee
{
/// <summary>
/// This Method will display details about Manager
/// </summary>
public void Display()
{
Console.WriteLine("Manager Class");
}
}
public class Clerk : Employee
{
/// <summary>
/// This Method will display details about Clerk
/// </summary>
public void DisplayClerk()
{
Console.WriteLine("Clerk Class");
}
}
public class Employee
{
static void Main(string[] args)
{
Console.WriteLine("Trainee Class Will be Moved");
}
/// <summary>
/// This is a main Method will display details about Manager,Clerk,Trainee
/// </summary>
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++.