2009-11-22 17 views
8

Estoy intentando invocar un método interno desde uno generado dinámicamente. El código il es simple: ldarg_0, callvirt, ret.¿Es posible invocar el método interno desde un método dinámico en .NET?

La ejecución del método falla con TypeLoadException diciendo que no puede cargar el tipo en el que se define el método interno.

Cuando lo pienso, esto parece lógico, porque el ensamblado de host de método dinámico no es amigo del ensamblado de tipo declarante del método.

Sin embargo, he esperado que el método dinámico siga funcionando, al igual que funciona Delegate.CreateDelegate. Después de todo, logré obtener MethodInfo del método interno, por lo que la barrera de permisos está detrás de mí.

De todos modos, la pregunta es "¿es posible invocar un método interno desde uno generado dinámicamente?"

Gracias.

EDIT:

Este es un ejemplo simple código que demuestra el 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); 
    } 
    } 
} 

En el código se crea dos delegados instancia abierta para acceder a la propiedad de instancia Data.String:

  • tipo getter1 seguro usando Delegate.CreateDelegate
  • tipo uns afe getter2 utilizando DynamicMethod

El tipo de delegado seguro creado por Delegate.CreateDelegate funciona, mientras que el que usa DynamicMethod falla con TypeLoadException.

Tenga en cuenta que no deseo tomar el enfoque tipo seguro, ya que el contexto en el que se crea el getter no es genérico. Por supuesto, puedo resolver este problema, pero la pregunta ahora es la del principal: ¿por qué DynamicMethod falla donde Delegate.CreateDelegate tiene éxito?

+0

Una TypeLoadException implica que no se puede encontrar el ensamblado, ¿qué dice el visor de registro de fusión? –

+0

El registro de fusión está vacío. No debería haber ningún problema para cargar el conjunto. Todos los ensamblajes involucrados están ubicados en la misma carpeta. – mark

+0

@JeremyMcGee tiene razón. Obtenga la lista de ensamblados cargados en AppDomain durante el modo de depuración y compruebe que el ensamblaje de destino esté allí. Además, es mejor poner tu código aquí para verificar. –

Respuesta

6

Funcionará si omite las comprobaciones de visibilidad.

cambiar esta línea

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

Ver msdn: (., En particular la mesa con todas las reglas)

Esto es de la mana en el constructor.

Tipo restrictedSkipVisibility: System.Boolean verdad para saltar JIT cheques de visibilidad sobre los tipos y miembros que accede el MSIL del método dinámico , con esta restricción: el nivel confianza de los conjuntos que contienen los los tipos y miembros deben ser ser iguales o menores que el nivel de confianza de la pila de llamadas que emite el método dinámico ; de lo contrario, falso.

+0

DynamicMethod no está en el estándar .net, ¿hay alguna manera de hacerlo en el estándar .net? – trampster

Cuestiones relacionadas