2009-10-30 19 views
13

Devo generare una classe utilizzando Reflection.Emit che implementa la seguente interfaccia.Utilizzo di Reflection.Emit per creare una classe che implementa un'interfaccia

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

Qualcuno ha un esempio di come emetterei quanto segue come un semplice caso di test?

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

Ho riscritto la domanda;) –

risposta

10

Se stai usando Reflection.Emit, si dovrebbe davvero prendere una copia del Reflection.Emit language add-in per Reflector. Anche se non è perfetto, dovrebbe ottenere almeno il 95% del modo in cui un determinato codice emesso.

+3

+1 Questo componente aggiuntivo è estremamente utile. –

+0

Il ReflectionEmitLanguage è semplicemente fantastico ... –

+0

-1 Mentre il componente aggiuntivo potrebbe essere (o potrebbe non esserlo, non so, non mi interessa, non uso Reflector, è costoso) estremamente utile, questo non risponde la domanda. – Szybki

0

Credo che AutoMapper e/o LinFu lo faranno per voi. È possibile creare un'istanza di un'interfaccia utilizzando AutoMapper, l'ho fatto.

+0

AutoMapper è così lento! –

+0

Questa è un'affermazione piuttosto ampia senza contesto. ymmv e dipende dal tuo utilizzo. http://ericlippert.com/2012/12/17/performance-rant/ – Maslow

+0

È possibile eseguire un semplice test su oltre 100000 elementi nell'array. Se lo scrivi senza automap, sarà 10 volte più veloce. Per il piccolo set credo che questa differenza non contenga ... –

3

Non ho un compilatore a portata di mano, ma qualcosa di simile dovrebbe funzionare:

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

Hai dimenticato di dialogo di ritorno:

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

Sembra, si vuole fare un rapido accesso alle proprietà dell'oggetto per il suo nome senza riflessione in fase di esecuzione. Utilizzando Yappi e la sua proprietà <> classe è possibile implementare data interfaccia come questa:

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

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

e quindi utilizzarlo in questo modo:

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

Avete ancora bisogno di IObject e il tipo di dinamica di costruzione?

Problemi correlati