Introduction
While working with a data bound application, I needed to use a DataSource
for several controls to form different hierarchies (Windows.Forms
and Web.UI.WebControls
). All of them had this property, but they didn't inherit it from a common ancestor class or interface. If DataSource
was a Method, delegates could be the way to factorize my code. As it isn't, there is no C# way to solve my problem.
The need
Let's take these two classes. They would share the same methods, or some of them, and the same properties but not the same base class or interface implementation; their common ancestor is object
. They also do pretty similar stuff. They're just not mine, so I can't modify the hierarchy.

Figure 1: Hierarchy "The Need" and a Client
Then I have this client class that can work with either of them through some method. I'll need to build a couple of overloads, doing exactly the same:
public class SomeAndAnotherClient
{
public void DoSomething(ISomeInterface some)
{
some.Method1();
some.Method2("string1", "string2");
int x = some.Property1;
string y = some.Property2;
}
public void DoSomething(IAnotherInterface some)
{
some.Method1();
some.Method2("string2", "string2");
int x = some.Property1;
string y = some.Property2;
}
}
Listing 1: Client class using overloads
This approach is bearable but it could become annoying if there were many situations like this in the same project, month... lifetime. Depends on how patient you might be, I'm not.
There is also another issue, later I might get a third class I like to use in the same task, also providing the same methods and properties and also with a common ancestor object. Now I would need to make a third overload, which is no problem, if you were patient. What if my product has been released? I'll need to release version two, just because I'd like to use a third class.
The proxy
Using a single proxy class, you can pack this problem into a single module, which can be updated whenever necessary.
public class SomeAndAnotherProxy {
protected SomeClass obj_SomeClass;
protected AnotherClass obj_AnotherClass;
public SomeAndAnotherProxy(SomeClass some) { ... }
public SomeAndAnotherProxy(AnotherClass another) { ... }
public int Property1 {
get
{
if (obj_SomeClass != null)
return obj_SomeClass.Property1;
else return obj_AnotherClass.Property1;
}
}
public void Method1() {
if (obj_SomeClass != null)
obj_SomeClass.Method1();
else obj_AnotherClass.Method1();
}
}
Listing 2: Proxy class
Now that I have a guy to proxy for me, I don't need overloads in my client class. The really hard task is to add a new class to my proxy; I'll need to create new constructor overloads and add conditional lines to every single property and method.
I'm not patient, proxy isn't good enough.
Delegates-based proxy
Let's imagine we are dealing with methods only, no properties on "Some" and "Another" classes. I could then create a delegate type for every method "kind" (signature) and an assignable member of the correct delegate type for each method; I'll name each member the same as the method they would reference to.
public class DelegatesProxy {
public delegate void Method1Dlg();
public delegate void Method2Dlg(params string[] args);
public Method1Dlg Method1;
public Method2Dlg Method2;
}
public static class UsingAllOfIt {
public static void UsingDelegatesProxy()
{
SomeClass some = new SomeClass() ;
AnotherClass another = new AnotherClass() ;
DelegatesProxy proxy = new DelegatesProxy();
proxy.Method1 += some.Method1;
proxy.Method2 += some.Method2;
SomeAndAnotherClient.DoSomething(proxy);
proxy = new DelegatesProxy();
proxy.Method1 += another.Method1;
proxy.Method2 += another.Method2;
}
}
Listing 3: Proxy and delegates
Love this approach!! Don't you? Every time I want to include a new class, I need to change... absolutely nothing, just create a proxy instance and correctly bind all the methods to their delegates. Unfortunately, there are issues here. It is easy to make mistakes, for instance: I could bind members incorrectly and I cannot reference properties using delegates. Beautiful, but still not enough.
Delegates and properties
I'll take a couple of delegates, one for "set" one for "get", we could also think of indexable properties, but this extension can be done easily, and as now we are talking C#, no indices for properties.
public class DelegatesProxyWithProperies : DelegatesProxy
{
public delegate string get_Property1Dlg();
public delegate int get_Property2Dlg();
public delegate void set_Property2Dlg();
public get_Property1Dlg get_Property1;
public set_Property2Dlg set_Property2;
public get_Property2Dlg get_Property2;
}
Listing 4: A proxy with property delegates
We can reference both methods and delegates now. We'll need to use Reflection to create getter and setter references.
proxy.get_Property1 += (DelegatesProxyWithProperies.get_Property1Dlg)
Delegate.CreateDelegate(typeof(DelegatesProxyWithProperies.get_Property1Dlg),
some, "get_Property1");
proxy.get_Property2 += (DelegatesProxyWithProperies.get_Property2Dlg)
Delegate.CreateDelegate(typeof(DelegatesProxyWithProperies.get_Property2Dlg),
some, "get_Property2");
proxy.set_Property2 += (DelegatesProxyWithProperies.set_Property2Dlg)
Delegate.CreateDelegate(typeof(DelegatesProxyWithProperies.set_Property2Dlg),
some, "set_Property2");
Listing 5: Creating property delegates
Right here, we can completely encapsulate objects with similar properties and methods. Though it is so hard to write it down every time, we can make many, many mistakes doing so. I think this one is good, but there's something missing.
Just to make it easier
I created a class to make all this process easier. It plays the "Property Delegate" role.

Figure 2: A delegate for properties
You would access property delegate values through the property Value
. An implicit operator was implemented when using the property as a Right value. Unfortunately, the Left side assigns must be done through Value
.
PropertyDelegate<int> Property1 = new PropertyDelegate<int>(some, "Property1");
int x = Property1;
Console.WriteLine("x={0}", x);
Property1.Value = 12345 ;
x = Property1 ;
Console.WriteLine("x={0}", x);
Listing 6: Using property delegates
To create a class using this approach instead of lose delegates for setter and getter:
public class DelegatesProxyWithPropertyDelegates : DelegatesProxy
{
public PropertyDelegate<int> Property1;
public PropertyDelegate<string> Property2;
}
Listing 7: A proxy using PropertyDelegates
Using it will be just the same. There's another issue here. Properties can be read/write, readonly, or writeonly (which I've never used). I could (actually have) created three classes, one for each situation, changes nothing; right now, we bind properties to their delegates as if they were always read/write.
How about events?
If we want to include every interface-valid instance member, we cannot leave them aside. Events behave pretty much like properties, they just don't have accessors but "add" and "remove" operations. Even easier, both add and remove use the same signature. Skipping the middle approach I used for properties, an event delegate would look like:

Figure 3: Event delegates
DelegateType
represents the event type. As I cannot use System.Delegate
on Generics constrains, it is unconstrained and there is a clear mistake that can be made by using it. Once more, be careful when using this. There is a useful feature here. Events are never assigned to or from, so an implicit operator in both directions is not useful, but overloading "+" and "-" operators, we get a great result. We can use them as if they were the original events.
EventDelegate<EventHandler> handler =
new EventDelegate<EventHandler>(some, "Event1");
handler += new EventHandler(Handler);
some.OnEvent1(EventArgs.Empty);
handler -= new EventHandler(Handler);
some.OnEvent1(EventArgs.Empty);
Listing 8: Using event delegates
In the previous listing, OnEvent1
is just a public trigger for the event Event1
.
Putting it all together
So far we have a proxy class with members that can reference methods, properties, and events. Let's create a proxy class using all of it.
public class FullProxy
{
public delegate void Method1Dlg();
public delegate void Method2Dlg(params string[] args);
public Method1Dlg Method1;
public Method2Dlg Method2;
public ReadOnlyPropertyDelegate<int> Property1;
public PropertyDelegate<string> Property2;
public EventDelegate<EventHandler> Event1;
}
Listing 9: A full proxy
Using these class instances, we can completely encapsulate, in the same way we used to do using interfaces, types from different hierarchies.
FullProxy full = new FullProxy();
full.Method1 = new FullProxy.Method1Dlg(some.Method1);
full.Method2 = new FullProxy.Method2Dlg(some.Method2);
full.Property1 = new ReadOnlyPropertyDelegate<int>(some, "Property1");
full.Property2 = new PropertyDelegate<string>(some, "Property2");
full.Event1 = new EventDelegate<EventHandler>(some, "Event1");
full.Event1 += Handler;
some.OnEvent1(EventArgs.Empty);
full.Method1();
full.Method2("string1", "string2");
full.Property1.Value = (int)DateTime.Now.Ticks;
int x = full.Property1; int y = full.Property1.Value; string s = full.Property2;
Listing 10: Using a full proxy
Definitely this is the one, it just needs some makeup.
The rules
Let's encapsulate the type Hypothetical
. We should only care for the interface valid members: Methods, Properties, and Events.
<visibility> <type_descriptor> Hypothetical
{
// 1 .. N1 Read / Write Properties
Type1i Property1i { get ... set ...}
// 1 .. N2 Readonly Properties
Type2i Property2i { get ... }
// 1 .. N3 Writeonly Properties
Type3i Property3i { set ... }
// 1 .. N4 Methods Type4i
Methodi(<parameter_specs>i)
// 1 .. N5 Events
event Type5i Eventi;
}
// <type_descriptor> : class | struct | interface
Listing 11: Hypothetical type
Encapsulating the proxy for Hypothetical
will be:
public class HypotheticalProxy
{
// 1 .. N1 Read / Write Properties
public PropertyDelegate<Type1i> Property1i ;
// 1 .. N2 Readonly Properties
public ReadOnlyPropertyDelegate<Type2i> Property2i ;
// 1 .. N3 Writeonly Properties
public WriteOnlyPropertyDelegate<Type3i> Property3i ;
// 1 .. N4 Methods
delegate Type4i MethodiDlg(<parameter_specs>i) ;
public MethodiDlg Methodi ;
// 1 .. N5 Events
public event Type5i Eventi ;
}
Listing 12: Hypothetical proxy
So far
Let's see what problems we still might have:
- Wrong binds:
- Not existing members.
- Wrong member types and/or parameters.
- Wrong members, e.g., two methods F and G having the same signature and binding method F on target to field G on proxy, G on target to field F on proxy.
- Inconsistent accessor for properties, e.g., bind a readonly property to a read/write property delegate.
- Slow member invocations.
- Slow binds.
Bindings can be automated so these mistakes won't be made. Member invocations proved to be fast enough, see statistics. Bindings will be slow, some approaches will be used to make this a minor issue, but if you need to bind once and use many times, there is not going to be great performance degradation on your application; for multiple bindings, it definitely will.
Automating bindings
Creating classes which can do all binding work, we get:

Figure 4: DynamicInterface
After shaping my library a little, I get this. Member delegates and a DynamicInterface
. Proxies will decent from DynamicInterface
. Descendents of DynamicInterface
are supposed to define only fields of type PropertyDelegate
for read/write properties, ReadOnlyPropertyDelegate
for readonly properties, EventDelegate
for events and delegates for methods.
public class DynamicInterfaceProxy : DynamicInterface
{
public delegate void Method1Dlg();
public delegate void Method2Dlg(params string[] args);
public Method1Dlg Method1;
public Method2Dlg Method2;
public ReadOnlyPropertyDelegate<int> Property1;
public PropertyDelegate<string> Property2;
public EventDelegate<EventHandler> Event1;
public DynamicInterfaceProxy() {}
public DynamicInterfaceProxy(object instance) : base(instance) { }
}
Listing 13: Creating dynamic interface descendents
Looks pretty much the same as FullProxy
, isn't it? DynamicBind
iterates through all fields in descendent types, binding them to correct members, delegates to methods, ReadonlyPropertyDelegate
fields to readonly properties, EventDelegate
fields to events, and so. Now I have two ways to bind proxies with targets, during proxy creation or using DynamicBind
.
SomeClass some = new SomeClass();
AnotherClass another = new AnotherClass();
DynamicInterfaceProxy dynProxy = new DynamicInterfaceProxy(some);
dynProxy.Event1 += Handler;
some.OnEvent1(EventArgs.Empty);
dynProxy.DynamicBind(another);
dynProxy.Event1 += Handler;
another.OnEvent1(EventArgs.Empty);
Listing 14: Binding proxies
Speeding bindings up
I've been using Reflection a lot. Reflection works great, but slow, very. Let's use Reflection but just one time, like a compiler would. Instead of binding member by member using Reflection, I will create (using emit) a class to do fast bindings; class creation would be slow, but you can do it just once for the whole application execution. I'll allow saving this binding class, just in case you would want it for later use or want to create the binder class just once.

Figure 5: Binders
A binder will contain the exact code needed to make assigns pretty fast. The bindings generator creates a class for every <Proxy, Target> pair you want and places them into a dynamically generated assembly which can be saved and be statically used later.
I guess naming them "static" is not quite correct, but as they can be used statically or dynamically, I chose to name them after the most attractive way.
Now let's take a very small proxy and see how it works:
public class SmallProxy
{
PropertyDelegate<string> Property2;
}
...
BindingsGenerator gen = new BindingsGenerator("Small");
IStaticBinder<SmallProxy, SomeClass> binder =
gen.CreateStaticBinder<SmallProxy, SomeClass>();
gen.SaveAssembly("c:\\temp");
...
SmallProxy small = binder.Bind(some);
Listing 15: Binder generation
The instance binder obtained from CreateStaticBinder
can be used to do SmallProxy
to SomeClass
bindings, and we can include a reference to c:\temp\Small.dll in our project to do the same. There are two overloads for the method CreateStaticBinder
. Use the generic one if you know both the Proxy and Target types at compile time.
Binder from the inside

Figure 6: ILDasm look at a binder
Using ILDasm Small.dll, we can see it contains a type named SomeClass_TO_SmallProxy
. This naming I chose for binder types to be easily recognized for later use. You can have as many binders as you want in one assembly; just avoid naming conflicts. Type names are quite long because I'm using Generics and nested types.
Close look at Bind, also from the inside
Now let's take a look at the MSIL code generated by BindingsGenerator
. Type names have been simplified so they are readable.
.method public hidebysig virtual final instance class SmallProxy
Bind(class SomeClass [1]) cil managed
{
.maxstack 5
.locals init (class SmallProxy [0])
newobj instance void SmallProxy::.ctor()
stloc.0
ldloc.0
ldarg 1
ldftn instance string SomeClass::get_Property2()
newobj instance void class PropertyDelegate<string>/PropertyGetter<string>::
.ctor(object, native int)
ldarg 1
ldftn instance void SomeClass::set_Property2(string)
newobj instance void class PropertyDelegate<string>/PropertySetter<string>::
.ctor(object,native int)
newobj instance void class PropertyDelegate<string>::
.ctor(class PropertyDelegate<string>/PropertyGetter<string>,
class PropertyDelegate<string>/PropertySetter<string>)
stfld class PropertyDelegate<string> SmallProxy::Property2
ldloc.0
ret
}
Listing 17: Bind's MSIL
First things first: BindingsGenerator
creates the resulting instance using the default constructor and stores it in a local variable, proxies must have one. Later, it creates delegates for both the getter and setter using the target instance and a function pointer. Then it creates a PropertyDelegate
using both delegates and stores it in the Property1
field. In the end, it loads SmallProxy
on the stack to be returned. For readonly and writeonly properties, it will generate the creation of a single delegate. For events, again two delegates will be created. There will be as many blocks as there are members in the proxy.
BindingsGenerator
does pretty much the same a compiler would if it supports encapsulation. Instead, a compiler could generate a binder for every kind of assign used.
Runtime statistics
Would it be faster? It is impossible to tell without testing it. Let's take CompleteProxy
and test some loops:
public class CompleteProxy : DynamicInterface
{
public PropertyDelegate<string> Property2;
public ReadOnlyPropertyDelegate<int> Property1;
public WriteOnlyPropertyDelegate<string> Property3;
public EventDelegate<EventHandler> Event1;
public delegate void Method1Dlg();
public delegate void Method2Dlg(params string[] args);
public Method1Dlg Method1;
public Method2Dlg Method2;
}
...
DateTime start = DateTime.Now;
for (int count = 0; count <= 10000; count++)
{
}
DateTime end = DateTime.Now ;
DisplayStats(start, end) ;
Listing 18: Benchmark code
Table 1: Benchmark results
Loop |
Code |
Time (ms) |
Some dynamic bound
|
dynamicProxy.DynamicBind(some);
dynamicProxy.Method1();
|
3890
|
Some static bound
|
staticProxy = binder.Bind(some);
staticProxy.Method1() ;
|
1640
|
Direct call
|
some = new Some() ;
some.Method1() ;
|
1578
|
Some dynamic bound, Init
|
dynamicProxy.Method1() ;
|
1546
|
Some static bound, Init
|
staticProxy.Method1() ;
|
1531
|
Direct call, Init
|
some.Method1() ;
|
1562
|
Dynamic assigns are clearly the worst; dynamic are only a little bit slower than creating instances of SomeClass
directly; this behavior will not always be like this. Target class constructions can take much time, they might need for resources to become ready or so, and proxy instances just need to initialize their members, it will always take the same time. Once bound, no loop seems to be faster or slower.
Let's dream
If Anders Hejlsberg likes this idea, he might include this on C# 4. Same as yield
and value
; they can include a new context sensitive keyword encapsulation
which will be used like this.
public encapsulation Proxy
{
int Property1 {get;}
string Property2 { get; set; }
void Method1();
void Method2(params string[] args);
event EventHandler Event1 ;
}
Listing 19: The sweetest dream about C# 4
The C# compiler will generate a class like my DynamicInterface
. Some custom attributes could help when using proxies so IDEs show members as what they represent (properties, methods, events) instead of what they actually are (fields).
public class Proxy
{
public void delegate Method1Dlg() ;
public void delegate Method2Dlg() ;
[ShowAs(AutoCompleteStyle.Property)]
public ReaonlyPropertyDelegate<int> Property1 ;
[ShowAs(AutoCompleteStyle.Property)]
public PropertyDelegate<string> Property2 ;
[ShowAs(AutoCompleteStyle.Method)]
public Method1Dlg Method1 ;
[ShowAs(AutoCompleteStyle.Method)]
public Method2Dlg Method2 ;
[ShowAs(AutoCompleteStyle.Event)]
public EventDelegate<EventHandler> ;
}
Listing 20: Dream C# 4 generated proxy
For every assign, they would generate MSIL similar to that my BindingsGenerator
creates. Two solutions are possible: in-lining code for initializing all fields in the proxy, or creating a class to do the job (like binders).
Conclusions: Should I say TO DOs
I still need to fix much, but I think this library is already useful. I think this concept may help many developers or at least hope so. I still need to delegate indexers but it is not difficult. I also need to throw better messages in my Exceptions.
References
- Meyer Bertrand: Object-Oriented Software Construction Second Edition. Prentice Hall, 2002.
- Lidin Serge: Inside Microsoft .NET IL Assembler. Microsoft Press, 2002.
- Barr Daniel: Three C# Tips: Indexed properties, property delegates, and read-only subproperties. csharptips.aspx.
- Call properties through delegates and pass them by Reference, http://geekswithblogs.net/akraus1/archive/2006/02/10/69047.aspx.