【发布时间】:2012-07-16 22:17:54
【问题描述】:
我遇到了这样一种情况:函数表达式树 Expression<Func<TClass, TProperty>> 被分配给 object 类型的全局变量,然后在我需要的代码中用表达式调用不同的方法。我无法更改全局对象类型;它必须是对象。
除非我将对象转换为Expression<Func<TClass, TProperty>>,否则尝试使用全局对象调用第二个方法时,代码不会编译。问题是在调用第二种方法时我不知道 TProperty 是什么。
我创建了一个快速演示应用程序来说明这一点(用 VS2010 编写的 c# 控制台应用程序)——真正的应用程序看起来不像这样。
using System;
using System.Linq.Expressions;
namespace FuncExpressionTree
{
public class ViewModel
{
public string StringProperty { get; set; }
public int IntProperty { get; set; }
}
public class Helper<T>
where T : ViewModel
{
private object _global;
public void Execute()
{
AssignToGlobal((T vm) => vm.StringProperty);
ProcessGlobal();
AssignToGlobal((T vm) => vm.IntProperty);
ProcessGlobal();
}
public void AssignToGlobal<TClass, TProperty>(Expression<Func<TClass, TProperty>> expression)
{
_global = expression;
}
public void ProcessGlobal()
{
// invalid cast exception thrown when IntProperty is assigned to _global
AssignToGlobal((Expression<Func<T, string>>)_global);
}
}
class Program
{
static void Main(string[] args)
{
(new Helper<ViewModel>()).Execute();
}
}
}
如果我们专注于Execute() 方法。
- 第一个global 被赋值为字符串属性的表达式。
- ProcessGlobal 执行并正常工作,因为我正在投射到
Expression<Func<T, string>>。 - 下一个 global 被赋值为 int 属性的表达式。
- ProcessGlobal 再次执行,但此时抛出了无效的强制转换异常。如果我将其更改为强制转换为
Expression<Func<T, int>>它将起作用,但字符串属性将不起作用。Expression<Func<T, object>>也会抛出一个无效的强制转换异常。
我觉得我错过了一些东西,应该可以使用System.Linq.Expressions 命名空间来动态调用第二种方法(例如,上例中 ProcessGlobal 中的 AssignToGlobal)。
那么我怎样才能让它以一种通用的方式工作呢?
【问题讨论】:
标签: c# .net linq lambda expression-trees