14

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);
    }
}
Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
karma
  • 141
  • 1
  • 1
  • 3

5 Answers5

7

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.

Nicole Calinoiu
  • 20,843
  • 2
  • 44
  • 49
  • 4
    -1 While the add-in may be (or may be not, I don't know nor care, I don't use Reflector, it's expensive) extremely useful, this does not answer the question. – Szybki Feb 08 '18 at 18:55
4

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();
kvb
  • 54,864
  • 2
  • 91
  • 133
  • Hello, i have used your example successfully (minor code edits). After i create the generatedType, i use Activator.CreateInstance(generatedType) to get a hold on the object. I cast it as the interface IObject, and then i call the method. Indeed, it gives me default(T). What i require is to change that implementation, and instead of giving me default(T), to hook in with a generic method that receives those parameters (or the list of parameters) and gives a proper implementation. Any idea on how to achieve that? – Darksody Jul 31 '19 at 14:36
  • @Darksody - Sorry, I can't tell from your description exactly what you mean. It would probably be best to open a new question that clearly lays out the specifics. – kvb Aug 02 '19 at 20:58
0

I believe AutoMapper and/or LinFu will do this for you. You can definitely create an instance of an interface using AutoMapper, I've done it.

Maslow
  • 18,464
  • 20
  • 106
  • 193
  • AutoMapper is so slow! – Milan Jaric Jan 30 '14 at 12:56
  • That's a pretty broad statement with no context. ymmv and it depends on your usage. http://ericlippert.com/2012/12/17/performance-rant/ – Maslow Jan 30 '14 at 14:58
  • You can do simple test over 100000 items in array. If you write it whithout automap it will be 10 times faster. For small set i belive this difference doesn't matter... – Milan Jaric Jan 31 '14 at 08:29
  • But performance bottlenecks is not only abot specific line of code. Imagibe when some method where that line of code is executed very frequently then Im sure you would consider changing the way how it is implemented ;) – Milan Jaric Jan 31 '14 at 08:32
  • did you look at the article I linked at all? – Maslow Jan 31 '14 at 15:18
0

You forgot to BOX the return:

internal delegate object FastConstructorHandler(object[] paramters);

    private static FastConstructorHandler CreateDelegate(Type Tipo)
    {
        DynamicMethod dynamicMethod = new DynamicMethod(string.Empty,
            typeof(object), new Type[] { typeof(object[]) }, Tipo.Module, false);

        ILGenerator ilg = dynamicMethod.GetILGenerator();

        ilg.DeclareLocal(Tipo);
        ilg.Emit(OpCodes.Ldloca_S, (byte)0);
        ilg.Emit(OpCodes.Initobj, Tipo);
        ilg.Emit(OpCodes.Ldloc_0);
        ilg.Emit(OpCodes.Box, Tipo);
        ilg.Emit(OpCodes.Ret);

        return (FastConstructorHandler)dynamicMethod.CreateDelegate(typeof(FastConstructorHandler));
    }
uildson
  • 11
0

It seems, you want to make fast access to object's properties by its name without reflection at run time. Using Yappi and its Property<> class you can implement given interface like this:

class GeneratedObject : IObject
{
    public string Value { get { return "Test"; } }

    public T Get<T>(string propertyName)
    {
        return Property<GeneratedObject>.Get<T>(this,propertyName);
    }
}

and then use it like this:

IObject obj = new GeneratedObject();
var value = obj.Get<String>("Value"); //value contains "Test"

Do you still need IObject and dynamic type construction?

Kelqualyn
  • 489
  • 5
  • 7