如何将Expression <Func <T,DateTime >>转换为Expression <Func <T,object >>

ant*_*ioh 58 c# lambda

我一直在寻找,但我找不到如何从该类型转换

Expression<Func<T, DateTime>>
Run Code Online (Sandbox Code Playgroud)

到类型:

Expression<Func<T, object>>
Run Code Online (Sandbox Code Playgroud)

所以我必须再次转向SO的广博知识;)

Jon*_*eet 74

你不能只是在他们之间施放,因为他们不是同一种东西.但是,您可以在表达式树中有效地添加转换:

using System;
using System.Linq.Expressions;

class Test
{
    // This is the method you want, I think
    static Expression<Func<TInput,object>> AddBox<TInput, TOutput>
        (Expression<Func<TInput, TOutput>> expression)
    {
        // Add the boxing operation, but get a weakly typed expression
        Expression converted = Expression.Convert
             (expression.Body, typeof(object));
        // Use Expression.Lambda to get back to strong typing
        return Expression.Lambda<Func<TInput,object>>
             (converted, expression.Parameters);
    }

    // Just a simple demo
    static void Main()
    {
        Expression<Func<string, DateTime>> x = text => DateTime.Now;
        var y = AddBox(x);        
        object dt = y.Compile()("hi");
        Console.WriteLine(dt);
    }        
}
Run Code Online (Sandbox Code Playgroud)


Roo*_*ian 25

RobJon Skeet的答案有一个问题.

你得到类似的东西x => Convert(x.PropertyName),但是例如对于ASP.NET MVC,你想要一个像这样的表达式x => x.PropertyName

所以Expression.Convert"污染"的一些情况表达.

解:

public static class LambdaExpressionExtensions
{
    public static Expression<Func<TInput, object>> ToUntypedPropertyExpression<TInput, TOutput> (this Expression<Func<TInput, TOutput>> expression)
    {
        var memberName = ((MemberExpression)expression.Body).Member.Name;

        var param = Expression.Parameter(typeof(TInput));
        var field = Expression.Property(param, memberName);
        return Expression.Lambda<Func<TInput, object>>(field, param);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

Expression<Func<T, DateTime>> expression = ...;
Expression<Func<T, object>> expr = expression.ToUntypedPropertyExpression();
Run Code Online (Sandbox Code Playgroud)

  • 这似乎不起作用.例如,我似乎无法将`Int32`转换为`object`; 这就是`Convert`调用的用途.没有它,我得到一个'ArgumentException`.尝试`DateTime`版本,同样的事情.如果这对你有用,我猜你是用引用类型做的. (7认同)

Rob*_*Rob 11

基于Jon的代码(感谢顺便说一句),您可以更进一步,以获得完全的灵活性:

public static Expression<Func<TModel, TToProperty>> Cast<TModel, TFromProperty, TToProperty>(Expression<Func<TModel, TFromProperty>> expression)
{
    Expression converted = Expression.Convert(expression.Body, typeof(TToProperty));

    return Expression.Lambda<Func<TModel, TToProperty>>(converted, expression.Parameters);
}
Run Code Online (Sandbox Code Playgroud)