添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
好帅的西装  ·  Vue3.0 ...·  1 年前    · 
火星上的紫菜汤  ·  Node.js 数组 forEach ...·  2 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I've been searching but I can't find how to cast from the type

Expression<Func<T, DateTime>>

to the type:

Expression<Func<T, object>>

So I must turn again to the SO vast knowledge ;)

You can't just cast between them, as they're not the same kind of thing. However, you can effectively add a conversion within the expression tree:

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);
                This generates the same output as just making an Expression<Func<T, object>> while declaring x => x.TodayValue. It ends up creating an expression that contains the "Convert()" method in the body and crashes some things like Linq to Entities. Is there any way to make it work for such scenario?? Thanks.
– CesarD
                Apr 23, 2018 at 12:56
                @CesarD: It's not something I've tried to do, I'm afraid, so I don't have anything to suggest.
– Jon Skeet
                Apr 23, 2018 at 15:48

The answers from Rob and Jon Skeet have one problem.

You get something like x => Convert(x.PropertyName), but often for instance for ASP.NET MVC you want an expression like this x => x.PropertyName

So Expression.Convert is "polluting" the expression for some cases.

Solution:

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);

Usage:

Expression<Func<T, DateTime>> expression = ...;
Expression<Func<T, object>> expr = expression.ToUntypedPropertyExpression();
                This doesn't seem to work. For example, I don't seem to be able to convert Int32 to object; that is what the Convert call is for. Without it I get an ArgumentException. Trying the DateTime version, same thing. If this worked for you, I'm guessing you did it with a reference type.
– Dave Cousineau
                Sep 13, 2015 at 19:03
                @rookian can you please suggest a way to use your solution for a nested property ? as of now, it works like a charm for the direct properties, but i need to access the nested or child properties. so please give an updated version if possible. Thanks
– Hardik Fefar
                Apr 3, 2018 at 6:46

Based on the code from Jon (thanks btw) you can take it one step further for complete flexibility:

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);

Just define the out TResult as object and compile the expression, it works for all data types;

Expression<Func<string, object>> dateExp = text => DateTime.Now;
object dt = dateExp.Compile()("hi");
Console.WriteLine(dt);

Fiddle sample here

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.

Restrictions.On(_func) - Variable 'p' of type 'Product' referenced from scope'', but it is not defined on passthrough See more linked questions