An implementation of latent typing for .NET
This small utility is an experimental implementation of the so-called latent typing for .NET, using C#.
What is Latent Typing
In .NET, you can treat types in an unified way only if they implement a common interface or have a common base class.
Of course, all .NET types have the common base class System.Object
, but the usefulness of treating different types as System.Object
is limited if you want to do more than store them.
Sometimes, you want to treat different types in a unified way even though they do not have a meaningful common base class or implement a common interface.
For example, you might want to store all objects in your program that have a Font
property of type Font
in a collection. Of course, there are various types that have a Font
property but have not much in common. So there is no way to cast them to a common base type or common interface.
Latent typing offers a solution to this problem. You would simply define an interface like:
interface IHasFont { Font Font { get; set; } }
None of the types you want to store implement this interface, but they all could implement it since they have the required property accessor methods. Normally, you would just write a wrapper class for each type that implements the required interface and delegates the implementation to the wrapped class. The AutoCaster does this automatically using System.Reflection.Emit
.
Here is an example of how you might use the AutoCaster mechanism:
System.Windows.Forms.Button button1=new Button("Foo");
System.Windows.Forms.ListViewItem listViewItem1=new ListViewItem("Bar");
System.Windows.Forms.FontDialog fontDialog1=new FontDialog();
List<IHasFont> items=new List<IHasFont>();
items.Add(Latent<IHasFont>.Cast(button1));
items.Add(Latent<IHasFont>.Cast(listViewItem1));
items.Add(Latent<IHasFont>.Cast(fontDialog1));
foreach(IHasFont x in items)
x.Font=new Font("Times New Roman",12);
Dangers of using latent typing
The issue of latent typing will usually lead to a religious debate between advocates of static and dynamic type systems. This sums up the debate very well. Obviously, I think that there are some cases where latent typing is useful. But you have been warned!
The Code
The class uses reflection and emits MSIL code, so you need various permissions to run it. It is, in my honest opinion, also a nice sample for reflection and automatically emitting MSIL. I use prototypes since Activator.CreateInstance
is too slow to use every time a new wrapper instance is required.
The code uses some .NET 2.0 features such as generics. But the automatic wrapper generation should also work under .NET 1.0 and .NET 1.1.
The code uses System.Reflection.Emit
to create the wrappers, so the first use of a wrapper carries a severe performance penalty. But once the wrapper is generated and JITed, calling a method will be much faster than dynamic invocation.
License
This code is provided under a BSD license. In other words: do whatever you want with it but please don't sue me if you break something :-)