Использование Reflection.Emit для создания класса, реализующего интерфейс - PullRequest
13 голосов
/ 30 октября 2009

Мне нужно сгенерировать класс с использованием Reflection.Emit, который реализует следующий интерфейс.

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

У кого-нибудь есть пример того, как я бы выпустил следующее в виде простого контрольного примера?

class GeneratedObject : IObject
{
    public T Get<T>(string propertyName)
    {
        // this is the simplest possible implementation
        return default(T);
    }
}

Ответы [ 5 ]

10 голосов
/ 30 октября 2009

Если вы используете Reflection.Emit, вам действительно нужно получить копию надстройки Reflection.Emit для языка для Reflector . Хотя он и не идеален, он должен дать вам по крайней мере 95% пути к любому данному излучаемому коду.

4 голосов
/ 30 ноября 2009

У меня нет удобного компилятора, но что-то вроде этого должно работать:

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 голосов
/ 31 июля 2011

Кажется, вы хотите сделать быстрый доступ к свойствам объекта по его имени без отражения во время выполнения. Используя Yappi и его класс Property <>, вы можете реализовать данный интерфейс следующим образом:

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

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

, а затем используйте его так:

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

Вам все еще нужны IObject и конструкция динамического типа?

0 голосов
/ 25 июня 2010

Вы забыли в поле возврата:

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 голосов
/ 19 ноября 2009

Я думаю, AutoMapper и / или LinFu сделает это за вас. Вы определенно можете создать экземпляр интерфейса с помощью AutoMapper, я сделал это.

...