Using Reflection.Emit to create a class implementing an interface

前端 未结 5 505
暗喜
暗喜 2020-12-14 04:03

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

public interface IObject
{
    T Get(string propertyName);         


        
相关标签:
5条回答
  • 2020-12-14 04:22

    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));
        }
    
    0 讨论(0)
  • 2020-12-14 04:24

    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.

    0 讨论(0)
  • 2020-12-14 04:28

    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?

    0 讨论(0)
  • 2020-12-14 04:30

    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.

    0 讨论(0)
  • 2020-12-14 04:46

    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();
    
    0 讨论(0)
提交回复
热议问题