Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to invoke internal method from a dynamic method in .NET?

I am trying to invoke an internal method from a dynamically generated one. The il code is simple: ldarg_0, callvirt, ret.

Executing the method fails with TypeLoadException saying it cannot load the type on which the internal method is defined.

When I think of it, this seems logical, because the dynamic method host assembly is not a friend of the method's declaring type assembly.

However, I have expected the dynamic method still to work, just like Delegate.CreateDelegate works. After all, I did manage to get the MethodInfo of the internal method, so the permissions barrier are behind me.

Anyway, the question is "is it possible to invoke an internal method from a dynamically generated one?"

Thanks.

EDIT:

Here is a simple code sample demonstrating the problem:

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);
    }
  }
}

In the code I create two open instance delegates to access the Data.String instance property:

  • type safe getter1 using Delegate.CreateDelegate
  • type unsafe getter2 using DynamicMethod

The type safe delegate created by Delegate.CreateDelegate works, while the one using DynamicMethod fails with the TypeLoadException.

Note, that I do not wish to take the type safe approach, since the context where the getter is created is not generic. Of course, I can solve this issue, but the question is now that of principal - why DynamicMethod fails where Delegate.CreateDelegate succeeds?

like image 262
mark Avatar asked Nov 22 '09 05:11

mark


1 Answers

It will work if you skip visibility checks.

Change this line

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

See msdn: (in particular the table with all the rules.)

This is from the doco on the constructor.

restrictedSkipVisibility Type: System.Boolean true to skip JIT visibility checks on types and members accessed by the MSIL of the dynamic method, with this restriction: the trust level of the assemblies that contain those types and members must be equal to or less than the trust level of the call stack that emits the dynamic method; otherwise, false.

like image 91
Sam Saffron Avatar answered Oct 21 '22 03:10

Sam Saffron