Click here to Skip to main content
13,593,097 members
Click here to Skip to main content
Add your own
alternative version


13 bookmarked
Posted 1 Apr 2006
Licenced CPOL

Protecting Writable Properties with an Interface Delegator

, 1 Apr 2006
Rate this:
Please Sign up or sign in to vote.
This article explains the use and implementation of an InterfaceDelegator. You may also find it to be a good example on building dynamic types using the System.Reflection.Emit namespace.


The InterfaceDelegator is a static class that can build a dynamic type that implements any interface passed in and forwards all the calls to an internal object that implements that interface. I created the InterfaceDelegator so I could protect myself and others from downcast errors. In the following example, you see a hack that I unfortunately I see often.

IReadOnly iRoObj = db.GetEntry(index);
((RealObjectType)iRoObj).Value = 1000;

Using the InterfaceDelegator, you can generate a wrapper object that users will not be able to downcast to your object type.

Using the Code

The following example shows how to create an InterfaceDelegator and how it is expected to behave:

public interface ITestClassReadOnly1
    int SomeInt{ get;}
    void TestOutParam(int inInt, out int outInt);

public interface ITestClassReadOnly2 : ITestClassReadOnly1
    string SomeString { get;}

public class TestClass1 : ITestClassReadOnly2 {...}

static void Main(string[] args)
    TestClass1 tClass = new TestClass1();
    ITestClassReadOnly2 iReadOnly = 

    if(iReadOnly is ITestClassReadOnly1)
        // this will pass
    if (iReadOnly is TestClass1)
        //this will fail
       // this will pass

InterfaceDelegator.Create will create a dynamic class that implements TT and forwards the calls to internal instance of TT. If the argument TT is not an interface, the call will return null.

Points of Interest

The DefineMethod method is a good example of how the InterfaceDelegator emits code to a dynamic type in a dynamic assembly.

private static void DefineMethod(MethodInfo methodInfo, TypeBuilder typeBuild, 
	FieldBuilder innerFieldBuild, bool isSystem_Object)
    // Build the parameter type array
    ParameterInfo[] methodParamInfos = methodInfo.GetParameters();
    int numParams = methodParamInfos.Length;

    Type[] paramTypes = new Type[numParams];
    for (int i = 0; i < numParams; i++)
        paramTypes[i] = methodParamInfos[i].ParameterType;

    MethodAttributes methodAttributes = (methodInfo.Attributes);

    // MethodAttributes to change if the method comes from System.object
    if (isSystem_Object)
        // Unset the MethodAttributes.NewSlot bit for the 
        // MethodAttributes of the new method
        methodAttributes &= ~MethodAttributes.NewSlot;

    // MethodAttributes to change if the method is an interface method
        // Unset the MethodAttributes.Abstract bit and add the Final bit 
        // for the MethodAttributes of the new method
        methodAttributes &= ~MethodAttributes.Abstract;
        methodAttributes |= MethodAttributes.Final;

    // Create the method
        MethodBuilder methodBuild = typeBuild.DefineMethod
				(methodInfo.Name, methodAttributes, 
				 methodInfo.ReturnType, paramTypes);

    // Build the implementation of the new method
    ILGenerator methodILGenerator = methodBuild.GetILGenerator();
    // Push this onto the stack
    methodILGenerator.Emit(OpCodes.Ldarg_S, 0);
    // Push _innerObj onto the stack 
    methodILGenerator.Emit(OpCodes.Ldfld, innerFieldBuild);
    // push the passed in arguments onto the stack
    for (int i = 1; i <= numParams; i++)
        methodILGenerator.Emit(OpCodes.Ldarg_S, i);
    // Call the method
    methodILGenerator.Emit(OpCodes.Callvirt, methodInfo);
    // return

The resulting code will look something like this in C#. In this case, the System.object.Equals was passed in to the first argument of DefineMethod.

public override bool Equals(object obj)
    return Equals(obj);

One other point this exercise has reminded me is to use caution when playing with generics and statics. For each new argument that is passed to a generic class, there will be a new instance of a static member variable. You can see an example of this with the _newDelegatorType member of the InterfaceDelegator class. When a different generic argument is passed in, _newDelegatorType will be null. This is also the reason for having the internal InterfaceDelegatorModuleBuilderProvider static class. Without this class, a new assembly would be built for each different generic argument passed into the InterfaceDelegator.


  • 2nd April, 2006 - I decided to see if I could use this code on Linux. I attempted to run the provided demo using the mono runtime. What I found was that I had some bugs. There was a difference in the output. The Equals and TestOutParam were not working. After taking a closer look at the IL that was generated, I discovered some problems with the MethodAttributes being used. The call to DefineMethodOverride was not needed. I also found that the MethodAttributes.NewSlot needed to be stripped off for methods that were being defined from System.object. I have uploaded the changes to the source and the demo.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Web Developer
United States United States
Bill has been a developer for a software company in Canonsburg PA for the past 7 years and a computer engineering student at the University of Pittsburgh prior to that.

Bill dreams of one day not having to develop code using COM, and finally being able to use .net.

You may also be interested in...

Comments and Discussions

GeneralIL vs. reflection Pin
meekmaak4-Apr-06 8:13
membermeekmaak4-Apr-06 8:13 
QuestionRe: IL vs. reflection Pin
billholmes544-Apr-06 8:30
memberbillholmes544-Apr-06 8:30 
AnswerRe: IL vs. reflection Pin
meekmaak4-Apr-06 12:43
membermeekmaak4-Apr-06 12:43 
Questionwhere oh where are your zips? Pin
fwsouthern1-Apr-06 17:17
memberfwsouthern1-Apr-06 17:17 
AnswerRe: where oh where are your zips? Pin
billholmes541-Apr-06 17:37
memberbillholmes541-Apr-06 17:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web03 | 2.8.180618.1 | Last Updated 1 Apr 2006
Article Copyright 2006 by billholmes54
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid