如何为 this/instance=null 动态调用非静态 System.Object::Equals(object)(例如通过反射)?
How to dynamically invoke non-static System.Object::Equals(object) for this/instance=null (e.g. through reflection)?
如何为 this==null 动态调用非静态 System.Object::Equals(object)
?
我有 C#:
Nullable<Int32> i1 = 33;
Nullable<Int32> i2 = 33;
i1 = null;
var ret = i1.Equals(i2); //note: i1==null
编译后执行无一例外都会得到ret
== false
。这是期望的行为。
IL 反汇编行 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'
在后台 - 运行时调用 System.Object::Equals(object)
(IL_0029) 方法 instance/this == null
如果我通过反射为 this/instance==null 调用 System.Object::Equals(object)
方法,我得到一个异常 System.Reflection.TargetException
"Non-static method requires a target."
调用代码:
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.'
如果在上面的代码中 i1
设置为某个数字,例如i1 = 3
。代码将正确执行。
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
我需要动态调用这个方法。
我无法将其更改为静态方法 '{Boolean Equals (System.Object, System.Object)}'。我在动态调用不同方法的大型项目中需要它。我以 Equals 为例。
反编译方法后System.Reflection.RuntimeMethodInfo.Invoke
。它似乎检查 this / instance == null 并抛出异常。
有什么方法可以绕过这个或其他方法吗?
您可以使用表达式树来编译并调用此代码:
Nullable<Int32> i1 = null;
Nullable<Int32> i2 = 33;
var equalsMethod = typeof(object)
.GetMethod("Equals",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
var call = Expression.Call(
Expression.Constant(i1, typeof(int?)),
equalsMethod,
Expression.Convert(Expression.Constant(i2), typeof(object)));
var lambda = Expression.Lambda<Func<bool>>(call).Compile();
Console.WriteLine(lambda()); // prints false
如何为 this==null 动态调用非静态 System.Object::Equals(object)
?
我有 C#:
Nullable<Int32> i1 = 33;
Nullable<Int32> i2 = 33;
i1 = null;
var ret = i1.Equals(i2); //note: i1==null
编译后执行无一例外都会得到ret
== false
。这是期望的行为。
IL 反汇编行 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'
在后台 - 运行时调用 System.Object::Equals(object)
(IL_0029) 方法 instance/this == null
如果我通过反射为 this/instance==null 调用 System.Object::Equals(object)
方法,我得到一个异常 System.Reflection.TargetException
"Non-static method requires a target."
调用代码:
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.'
如果在上面的代码中 i1
设置为某个数字,例如i1 = 3
。代码将正确执行。
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
我需要动态调用这个方法。 我无法将其更改为静态方法 '{Boolean Equals (System.Object, System.Object)}'。我在动态调用不同方法的大型项目中需要它。我以 Equals 为例。
反编译方法后System.Reflection.RuntimeMethodInfo.Invoke
。它似乎检查 this / instance == null 并抛出异常。
有什么方法可以绕过这个或其他方法吗?
您可以使用表达式树来编译并调用此代码:
Nullable<Int32> i1 = null;
Nullable<Int32> i2 = 33;
var equalsMethod = typeof(object)
.GetMethod("Equals",
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
var call = Expression.Call(
Expression.Constant(i1, typeof(int?)),
equalsMethod,
Expression.Convert(Expression.Constant(i2), typeof(object)));
var lambda = Expression.Lambda<Func<bool>>(call).Compile();
Console.WriteLine(lambda()); // prints false