【发布时间】:2009-04-08 09:50:30
【问题描述】:
我一直在搜索,但找不到如何从类型转换
Expression<Func<T, DateTime>>
到类型:
Expression<Func<T, object>>
所以我必须再次求助于如此广泛的知识;)
【问题讨论】:
我一直在搜索,但找不到如何从类型转换
Expression<Func<T, DateTime>>
到类型:
Expression<Func<T, object>>
所以我必须再次求助于如此广泛的知识;)
【问题讨论】:
您不能只在它们之间进行转换,因为它们不是同一种东西。但是,您可以有效地在表达式树中添加转换:
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);
}
}
【讨论】:
Rob 和 Jon 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);
}
}
用法:
Expression<Func<T, DateTime>> expression = ...;
Expression<Func<T, object>> expr = expression.ToUntypedPropertyExpression();
【讨论】:
Int32 转换为object;这就是Convert 调用的目的。没有它我会得到一个ArgumentException。尝试DateTime 版本,同样的事情。如果这对你有用,我猜你是用引用类型做的。
基于 Jon 的代码(感谢 btw),您可以更进一步以获得完全的灵活性:
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);
}
【讨论】:
只需将out TResult定义为对象并编译表达式,它适用于所有数据类型;
Expression<Func<string, object>> dateExp = text => DateTime.Now;
object dt = dateExp.Compile()("hi");
Console.WriteLine(dt);
【讨论】: