如果有问题的类型实现operator ==()
,那么我可以轻松地构建一个表达式来调用它。但是如果在基类中定义了运算符,它就不起作用 - 看看有三个断言通过但是一个失败了。
有没有正确的方法呢?
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Assert.IsTrue(new A(42) == new A(42)); // PASS
Assert.IsTrue(ExecuteOperatorEqual(new A(42), new A(42))); // PASS
Assert.IsTrue(new B(42) == new B(42)); // PASS
Assert.IsTrue(ExecuteOperatorEqual(new B(42), new B(42))); // FAIL
}
static bool ExecuteOperatorEqual<T>(T item1, T item2)
{
var expression = Expression.Lambda<Func<bool>>(
Expression.Equal(
Expression.Constant(item1),
Expression.Constant(item2)));
return expression.Compile()();
}
}
class A
{
private readonly int _value;
public A(int value)
{
_value = value;
}
public static bool operator ==(A left, A right) => left._value == right._value;
public static bool operator !=(A left, A right) => left._value != right._value;
}
class B : A
{
public B(int value) : base(value)
{
}
}
答案 0 :(得分:1)
我不确定它在您的上下文中是否有意义,但您可以解决将MethodInfo传递给您的问题Expression.Equal
static bool ExecuteOperatorEqual<T>(T item1, T item2)
{
BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;
var equalityMethod = typeof(T).GetMethod("op_Equality", bindingAttr, null, new Type[] { typeof(T), typeof(T) }, null);
var expression = Expression.Lambda<Func<bool>>(
Expression.Equal(
Expression.Constant(item1),
Expression.Constant(item2),
false,
equalityMethod
));
return expression.Compile()();
}
我已反映System.Core.dll
且Parameter
类未搜索任何重载运算符,如下所示:
private static MethodInfo GetUserDefinedBinaryOperator(ExpressionType binaryType, Type leftType, Type rightType, string name)
{
Type[] types = new Type[]
{
leftType,
rightType
};
Type nonNullableType = leftType.GetNonNullableType();
Type nonNullableType2 = rightType.GetNonNullableType();
BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
MethodInfo methodInfo = nonNullableType.GetMethodValidated(name, bindingAttr, null, types, null);
if (methodInfo == null && !TypeUtils.AreEquivalent(leftType, rightType))
{
methodInfo = nonNullableType2.GetMethodValidated(name, bindingAttr, null, types, null);
}
if (Expression.IsLiftingConditionalLogicalOperator(leftType, rightType, methodInfo, binaryType))
{
methodInfo = Expression.GetUserDefinedBinaryOperator(binaryType, nonNullableType, nonNullableType2, name);
}
return methodInfo;
}
添加BindingFlags.FlattenHierarchy
会找到相等运算符。他们必须有理由不将其添加到.Net
。