2009-11-22 12 views
8

Sto provando a richiamare un metodo interno da uno generato dinamicamente. Il codice è semplice: ldarg_0, callvirt, ret.È possibile richiamare il metodo interno da un metodo dinamico in .NET?

L'esecuzione del metodo non riesce con TypeLoadException che dice che non è possibile caricare il tipo su cui è definito il metodo interno.

Quando ci penso, questo sembra logico, perché l'assembly host del metodo dinamico non è un amico dell'assembly del tipo dichiarante del metodo.

Tuttavia, mi aspetto che il metodo dinamico funzioni ancora, proprio come funziona Delegate.CreateDelegate. Dopo tutto, sono riuscito a ottenere MethodInfo del metodo interno, quindi la barriera delle autorizzazioni è dietro di me.

In ogni caso, la domanda è "è possibile richiamare un metodo interno da uno generato dinamicamente?"

Grazie.

EDIT:

Ecco un esempio di codice semplice dimostrazione del problema:

using System; 
using System.Linq.Expressions; 
using System.Reflection; 
using System.Reflection.Emit; 

namespace A 
{ 
    internal class Data 
    { 
    internal string String { get; set; } 
    } 

    public static class Program 
    { 
    public static void Main() 
    { 
     Expression<Func<Data, string>> expr = x => x.String; 
     var getterInfo = ((PropertyInfo)((MemberExpression)expr.Body).Member).GetGetMethod(true); 
     var getter1 = (Func<Data, string>)Delegate.CreateDelegate(typeof(Func<Data, string>), getterInfo); 
     var dm = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object) }); 
     var gen = dm.GetILGenerator(); 
     gen.Emit(OpCodes.Ldarg_0); 
     gen.Emit(OpCodes.Castclass, typeof(Data)); 
     gen.Emit(OpCodes.Callvirt, getterInfo); 
     gen.Emit(OpCodes.Ret); 
     var getter2 = (Func<object, object>)dm.CreateDelegate(typeof(Func<object, object>)); 

     var data = new Data() { String = "Hello" }; 
     var str1 = getter1(data); 
     var str2 = getter2(data); 
    } 
    } 
} 

Nel codice creo due delegati istanza aperta per accedere alla proprietà di istanza Data.String:

  • digitare safe getter1 utilizzando Delegate.CreateDelegate
  • tipo uns afe getter2 utilizzando DynamicMethod

Il tipo di delegato sicuro creato da Delegate.CreateDelegate funziona, mentre quello che utilizza DynamicMethod ha esito negativo con TypeLoadException.

Si noti che non desidero adottare l'approccio di tipo sicuro, poiché il contesto in cui viene creato il getter non è generico. Ovviamente, posso risolvere questo problema, ma la domanda è ora quella del principale: perché DynamicMethod non riesce dove Delegate.CreateDelegate ha esito positivo?

+0

Un TypeLoadException implica che l'assembly non può essere trovato - cosa dice il visualizzatore di log di fusione? –

+0

Il registro di fusione è vuoto. Non ci dovrebbero essere problemi per caricare il gruppo. Tutti gli assembly coinvolti si trovano nella stessa cartella. – mark

+0

@JeremyMcGee ha ragione. Ottieni l'elenco degli assembly caricati nell'AppDomain durante la modalità di debug e controlla lì l'assembly di destinazione. Inoltre, è meglio mettere il codice qui per controllare. –

risposta

6

Funzionerà se si saltano i controlli di visibilità.

Modificare questa linea

var dm = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object) }, true); 

Vedi msdn: (. In particolare la tabella con tutte le regole)

Questo è dal doco sul costruttore.

Tipo restrictedSkipVisibility: System.Boolean true per ignorare JIT controlli visibilità sui tipi e membri accede il MSIL del metodo dinamico , con questa restrizione: il livello fiducia degli assembly che contengono tali i tipi e i membri devono essere uguale o inferiore al livello di fiducia dello stack di chiamate che emette il metodo dinamico ; altrimenti, falso.

+0

DynamicMethod non è in .net standard, un modo per farlo in .net standard? – trampster

Problemi correlati