其他分享
首页 > 其他分享> > 如何使用表达式树对数字类型应用隐式转换?

如何使用表达式树对数字类型应用隐式转换?

作者:互联网

我有一个带有int字段的ExpandoObject,我想使用表达式树将其转换为十进制.

这是我正在使用的方法:

private static Expression<Func<dynamic, decimal>> CreateLambdaCastExpression()
    {
        // source
        var sourceParameterExpression = Expression.Parameter(typeof (object), "source");

        var binder = Binder.GetMember(
            CSharpBinderFlags.None, "IntProp", typeof (ExpressionTreeUtils),
            new[] {CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)});
        // source.sourceProperty
        var sourcePropertyExpression = Expression.Dynamic(
            binder, typeof (object), sourceParameterExpression);

        // (decimal) source;
        var castedValueExpression = Expression.Convert(sourcePropertyExpression, typeof (decimal));

        // () =>  (decimal) source;
        return Expression.Lambda<Func<dynamic, decimal>>(castedValueExpression,
            sourceParameterExpression);
    }

以这种方式调用会导致InvalidCastException:

        dynamic source = new ExpandoObject();
        source.IntProp = 1;

        decimal r = CreateLambdaCastExpression().Compile()(source);

如果我将source.IntProp设置为1m,则可以(显然)

我在msdn上读到过,ExpressionConvert仅对用户定义的类型执行隐式转换,因此可能就是解释.

关于如何对数字类型执行隐式强制转换的任何想法吗?

解决方法:

更改这些行:

// CSharpBinderFlags.ConvertExplicit: explicit cast 
// (will convert double to decimal)
// CSharpBinderFlags.None: implicit cast
// (will convert int to decimal, won't convert double to decimal)
var convert = Binder.Convert(CSharpBinderFlags.ConvertExplicit, typeof(decimal), typeof(ExpressionTreeUtils));

// (decimal) source;
var castedValueExpression = Expression.Dynamic(
    convert, typeof(decimal), sourcePropertyExpression);

请注意有关隐式/显式强制转换的注释.

(因此唯一改变的是var castedValueExpression的构建方式)

ideone带有完整示例.

标签:dynamic,expandoobject,c,expression-trees
来源: https://codeday.me/bug/20191119/2039475.html