我最终遇到的情况是函数表达式树 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()
方法。
Expression<Func<T, string>>
。Expression<Func<T, int>>
,但是字符串属性不起作用,它将起作用。另外Expression<Func<T, object>>
会抛出无效的强制转换异常。我觉得我错过了一些东西,应该可以使用System.Linq.Expressions
命名空间来动态调用第二种方法(例如上例中ProcessGlobal中的AssignToGlobal)。
那么如何才能以通用方式实现这一目标呢?
答案 0 :(得分:1)
public void ProcessGlobal()
{
var globalType = _global.GetType(); // globalType = Expression<Func<TClass, TProperty>>
var functionType = globalType.GetGenericArguments()[0]; // functionType = Func<TClass, TProperty>
var functionGenericArguments = functionType.GetGenericArguments(); // v = [TClass, TProperty]
var method = this.GetType().GetMethod("AssignToGlobal").MakeGenericMethod(functionGenericArguments); //functionGenericArguments = AssignToGlobal<TClass, TProperty>
method.Invoke(this, new[] { this._global }); // Call AssignToGlobal<TClass, TProperty>)(this._global);
}