如何使用 long 或 int64 的表达式常量?

How to use expression constant with long or int64?

我有扩展方法

public static Expression<Func<T, bool>> ToExpression<T>(string operator, string name, object value)
{
    var parameter = Expression.Parameter(typeof(T));
    var memberExpression = Expression.Property(parameter, name);
    var constantExpression = Expression.Constant(value, typeof(memberExpression.Type));

    ....
    ..
    .
}

所以 Expression.Constant 为这样的数据抛出异常:

我正在使用这个 class:

public class Person{
    public    long Number{get;set;}
}

var person1 = new Person{ Number=123}
var person2 = new Person{ Number=9876543210}

person1 工作,但 person2 抛出异常“Argument types does not match”。

我该如何解决这个问题?

您必须在创建常量表达式之前转换值。

public static bool IsNullable(Type type)
{
    return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
}

public static Type ToUnderlying(Type type)
{
    if (type == null) throw new ArgumentNullException(nameof(type));

    if (IsNullable(type)) type = type.GetGenericArguments()[0];
    if (type.IsEnum      ) type = Enum.GetUnderlyingType(type);

    return type;
}

public static bool SafeConvert(object value, Type type, out object newValue)
{
    newValue = value;
    if (value == null)
    {
        if (!IsNullable(type))
            return false;
        return true;
    }

    var fromType = value.GetType();

    if (fromType == type)
        return true;

    if (IsNullable(type))
    {
        type = ToUnderlying(type);
    }

    newValue = Convert.ChangeType(value, type);
    return true;
}

public static Expression<Func<T, bool>> ToFilterExpression<T>(string operatorStr, string name, object value)
{
    var parameter = Expression.Parameter(typeof(T));
    var memberExpression = Expression.Property(parameter, name);

    if (!SafeConvert(value, memberExpression.Type, out var convertedValue))
        throw new Exception($"Cannot convert '{value}' to type '{memberExpression.Type.Name}'.");

    var constantExpression = Expression.Constant(convertedValue, memberExpression.Type);

    ...
}