private static BinaryExpression GetMethodBasedBinaryOperator(ExpressionType binaryType, Expression left, Expression right, MethodInfo method, bool liftToNull)
{
System.Diagnostics.Debug.Assert(method != null);
ValidateOperator(method);
ParameterInfo[] pms = method.GetParametersCached();
if (pms.Length != 2)
throw Error.IncorrectNumberOfMethodCallArguments(method, nameof(method));
if (ParameterIsAssignable(pms[0], left.Type) && ParameterIsAssignable(pms[1], right.Type))
{
ValidateParamswithOperandsOrThrow(pms[0].ParameterType, left.Type, binaryType, method.Name);
ValidateParamswithOperandsOrThrow(pms[1].ParameterType, right.Type, binaryType, method.Name);
return new MethodBinaryExpression(binaryType, left, right, method.ReturnType, method);
}
// check for lifted call
if (left.Type.IsNullableType() && right.Type.IsNullableType() &&
ParameterIsAssignable(pms[0], left.Type.GetNonNullableType()) &&
ParameterIsAssignable(pms[1], right.Type.GetNonNullableType()) &&
method.ReturnType.GetTypeInfo().IsValueType && !method.ReturnType.IsNullableType())
{
if (method.ReturnType != typeof(bool) || liftToNull)
{
return new MethodBinaryExpression(binaryType, left, right, method.ReturnType.GetNullableType(), method);
}
else
{
return new MethodBinaryExpression(binaryType, left, right, typeof(bool), method);
}
}
throw Error.OperandTypesDoNotMatchParameters(binaryType, method.Name);
}