How to cast Expression<Func<T, DateTime>> to Expression<Func<T, object>>

C#Lambda

C# Problem Overview


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

C# Solutions


Solution 1 - C#

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

Solution 2 - C#

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

Solution 3 - C#

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

Solution 4 - C#

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionantoniohView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#RookianView Answer on Stackoverflow
Solution 3 - C#RobView Answer on Stackoverflow
Solution 4 - C#LazZiyaView Answer on Stackoverflow