Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Reflection.Emit to create a class implementing an interface

I need to generate a class using Reflection.Emit that implements the following interface.

public interface IObject
{
    T Get<T>(string propertyName); 
}

Does anyone have an example of how I would emit the following as a simple test case?

class GeneratedObject : IObject
{
    public T Get<T>(string propertyName)
    {
        // this is the simplest possible implementation
        return default(T);
    }
}
like image 582
karma Avatar asked Oct 30 '09 18:10

karma


2 Answers

If you're using Reflection.Emit, you really ought to grab a copy of the Reflection.Emit language add-in for Reflector. While not perfect, it should get you at least 95% of the way to any given emitted code.

like image 154
Nicole Calinoiu Avatar answered Sep 28 '22 06:09

Nicole Calinoiu


I don't have a compiler handy, but something like this should work:

var aName = new AssemblyName("temp");
var appDomain = Threading.Thread.GetDomain();
var aBuilder = appDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Run);
var mBuilder = aBuilder.DefineDynamicModule(aName.Name);
var tBuilder = mBuilder.DefineType("GeneratedObject", TypeAttributes.Public | TypeAttributes.Class);
tBuilder.AddInterfaceImplementation(typeof(IObject));
var methBuilder = tBuilder.DefineMethod("Get", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual);
var typeParam = mb.DefineGenericParameters(new string[] { "T" })[0];
methBuilder.SetParameters(new Type[] { typeof(string) });
methBuilder.SetReturnType(typeParam);
var ilg = methBuilder.GetILGenerator();
let lBuilder = ilg.DeclareLocal(typeParam);
ilg.Emit(OpCodes.Ldloca_S, (byte)0);
ilg.Emit(OpCodes.Initobj, typeParam);
ilg.Emit(OpCodes.Ldloc_0);
ilg.Emit(OpCodes.Ret);
var generatedType = tBuilder.CreateType();
like image 23
kvb Avatar answered Sep 28 '22 06:09

kvb