DynamicMethod for ConstructorInfo.Invoke, what do I need to consider?

My question is:

If I am going to create a DynamicMethod object corresponding to ConstructorInfo.Invoke , what types of IL do I need to implement to handle all (or most) types of arguments, when can I guarantee that the correct type and number of arguments will be passed before I call?


Background

I am in the third iteration of my IoC container and am currently profiling to find out if there are any areas where I can easily shave off a lot of time.

One thing I noticed is that when resolving a particular type, I end up with a calling constructor using ConstructorInfo.Invoke , passing in an array of arguments that I developed.

What I noticed is that the invoke method has quite a bit of overhead, and I wonder if these are just different implementations of the same checks as me.

For example, due to the constructor matching code, I have to find a matching constructor for the predefined parameter names, types and values ​​that I went through, there is no way that this particular call would cause something like this to be able to handle, like the correct number of arguments, in the correct order, of the correct type and with the corresponding values.

, , DynamicMethod, , :

  • ConstructorInfo.Invoke: 1973ms
  • DynamicMethod: 93ms

20% . , ConstructorInfo.Invoke DynamicMethod, , 20% factory -scoped (.. ).

, , DynamicMethod .

, , ConstructorInfo, .

, , IL:

l001:    ldarg.0      ; the object array containing the arguments
l002:    ldc.i4.0     ; the index of the first argument
l003:    ldelem.ref   ; get the value of the first argument
l004:    castclass T  ; cast to the right type of argument (only if not "Object")
(repeat l001-l004 for all parameters, l004 only for non-Object types,
 varying l002 constant from 0 and up for each index)
l005:    newobj ci    ; call the constructor
l006:    ret

- , ?

, , , , " " ( ), , , .

+3
2

l004 l004: unbox.any T.

IL, , - , #, .

static void Test(object[] args)
{
  TestTarget((string)args[0], (int)args[1], (DateTime?)args[2]);
}

static void TestTarget(string s, int i, DateTime? dt){}

:

L_0000: ldarg.0 
L_0001: ldc.i4.0 
L_0002: ldelem.ref 
L_0003: castclass string
L_0008: ldarg.0 
L_0009: ldc.i4.1 
L_000a: ldelem.ref 
L_000b: unbox.any int32
L_0010: ldarg.0 
L_0011: ldc.i4.2 
L_0012: ldelem.ref 
L_0013: unbox.any [mscorlib]System.Nullable`1<valuetype [mscorlib]System.DateTime>
L_0018: call void Program::TestTarget(string, int32, valuetype [mscorlib]System.Nullable`1<valuetype [mscorlib]System.DateTime>)
L_001d: ret 
+1

, ( ) . , Fasterflect IL - , , , .

// note: class must have constructor with (int,string,string) signature
object obj = someType.CreateInstance( new { id=1, name="jens", foo="bar" } );

, , .

// try to map id, name and foo to constructor parameters
// allows changing the order and permit fallback to setting fields/properties
// e.g. might result in call to ctor(string,string) and set field "id"
object obj = someType.TryCreateInstance( new { id=1, name="jens", foo="bar" } );

: .

0

Source: https://habr.com/ru/post/1726796/


All Articles