jeudi 11 juin 2020

How to dynamically invoke non-static System.Object::Equals(object) for this/instance=null (e.g. through reflection)?

How to dynamically invoke non-static System.Object::Equals(object) for this==null?

I have C#:

Nullable<Int32> i1 = 33;
Nullable<Int32> i2 = 33;
i1 = null;

var ret = i1.Equals(i2); //note: i1==null

Execution after compilation will give ret == false with no exception. This is the desired behavior.

IL disassemby of line var ret = i1.Equals(i2); :

IL_001b: ldloca.s     i1
IL_001d: ldloc.1      // i2
IL_001e: box          valuetype [System.Runtime]System.Nullable`1<int32>
IL_0023: constrained. valuetype [System.Runtime]System.Nullable`1<int32>
IL_0029: callvirt     instance bool [System.Runtime]System.Object::Equals(object)
IL_002e: stloc.2      // 'ret'

Under the hood - runtime calls the System.Object::Equals(object) (IL_0029) method for instance/this == null

If I invoke System.Object::Equals(object)method through reflection for this/instance==null, I get an exception System.Reflection.TargetException "Non-static method requires a target."

Calling code:

Nullable<Int32> i1 = 33;
Nullable<Int32> i2 = 33;
i1 = null;

var equalsMethod = typeof(object).GetMethod("Equals", 
      System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);

var ret2= equalsMethod.Invoke(i1, new object[] { i2 }); //note: i1==null, throw exception 'Non-static method requires a target.'

If in the above code i1 is set to some number, e.g. i1 = 3. the code will execute correctly.

i1 = 3;
var equalsMethod = typeof(object)
    .GetMethod("Equals", 
    System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
var ret2= equalsMethod.Invoke(i1, new object[] { i2 }); //ret2 will be false

I need to dynamically invoke this method. I can't change it to the static method '{Boolean Equals (System.Object, System.Object)}'. I need it in a larger project that dynamically invoke different methods. I present Equals as an example.

After decompile method System.Reflection.RuntimeMethodInfo.Invoke. It seems to check if this / instance == null and throw an exception. Is there any way to bypass this or other way to do this?





Aucun commentaire:

Enregistrer un commentaire