如何构建可编译为 Func<T> 的表达式?
How can I build an expression that compiles to a Func<T>?
假设我有一个 returns T 的静态方法,例如:
T myT = MyClass.Create(type); // type is System.Type
然后我希望能够构建和编译一个表达式,这样我就可以得到一个 Func<T>
但我不知道该怎么做。
我可以为 Constant
构建它:
Func<T> result = Expression.Lambda<Func<T>>(Expression.Constant(string.Empty)).Compile()
但是对于 MyClass.Create(type)
我卡住了。
Func<T> result = ....?
感谢 usr
的提示,我设法使用 Expression.Call
做到了,所以给出:
public static class MyClass
{
public static string GetTime()
{
return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss,fff");
}
public static string GetName(Type type)
{
return type.Name;
}
}
然后:
// Calls static method GetTime with no args
var mCallGetTime = Expression.Call(typeof(MyClass), "GetTime", null);
Func<string> resultNoArg = Expression.Lambda<Func<string>>(mCallGetTime).Compile();
// The input param for GetName which is of type Type
var paramExp = Expression.Parameter(typeof(Type));
// Calls static method GetName passing in the param
var mCallGetName = Expression.Call(typeof(MyClass), "GetName", null, paramExp);
Func<Type, string> resultWithArg = Expression.Lambda<Func<Type, string>>(mCallGetName, paramExp).Compile();
// You can then call them like so... Print() just prints the string
resultNoArg().Print();
resultWithArg(typeof(string)).Print();
resultWithArg(typeof(int)).Print();
或者,代替:
var mCallGetTime = Expression.Call(typeof(MyClass), "GetTime", null);
我们可以使用以下方法组成 Expression.Call
:
// Get the method info for GetTime (note the Type[0] signifying no args taken by GetTime);
var methodInfo = typeof(MyClass).GetMethod("GetTime", new Type[0]);
var mCallGetTime = Expression.Call(methodInfo);
GetName
也是如此:
// Get the method info for GetName (note the new[] {typeof(Type)} signifying the arg taken by GetName
var getNameMethodInfo = typeof(MyClass).GetMethod("GetName", new[] { typeof(Type)});
var mCallGetName = Expression.Call(getNameMethodInfo, paramExp);
您的答案的替代方法是创建一个完全通用的方法,该方法将为任何类型的任何通用静态方法构造一个 Func<T>
。
public Func<T> BuildGenericStaticFunc<T>()
{
var type = typeof(T);
return Expression.Lambda<Func<T>>(
Expression
.Call(
type.GetMethod("Create", BindingFlags.Static | BindingFlags.Public)
.MakeGenericMethod(type),
Expression.Constant(type)
))
.Compile();
}
var result = BuildGenericStaticFunc<MyClass>();
假设我有一个 returns T 的静态方法,例如:
T myT = MyClass.Create(type); // type is System.Type
然后我希望能够构建和编译一个表达式,这样我就可以得到一个 Func<T>
但我不知道该怎么做。
我可以为 Constant
构建它:
Func<T> result = Expression.Lambda<Func<T>>(Expression.Constant(string.Empty)).Compile()
但是对于 MyClass.Create(type)
我卡住了。
Func<T> result = ....?
感谢 usr
的提示,我设法使用 Expression.Call
做到了,所以给出:
public static class MyClass
{
public static string GetTime()
{
return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss,fff");
}
public static string GetName(Type type)
{
return type.Name;
}
}
然后:
// Calls static method GetTime with no args
var mCallGetTime = Expression.Call(typeof(MyClass), "GetTime", null);
Func<string> resultNoArg = Expression.Lambda<Func<string>>(mCallGetTime).Compile();
// The input param for GetName which is of type Type
var paramExp = Expression.Parameter(typeof(Type));
// Calls static method GetName passing in the param
var mCallGetName = Expression.Call(typeof(MyClass), "GetName", null, paramExp);
Func<Type, string> resultWithArg = Expression.Lambda<Func<Type, string>>(mCallGetName, paramExp).Compile();
// You can then call them like so... Print() just prints the string
resultNoArg().Print();
resultWithArg(typeof(string)).Print();
resultWithArg(typeof(int)).Print();
或者,代替:
var mCallGetTime = Expression.Call(typeof(MyClass), "GetTime", null);
我们可以使用以下方法组成 Expression.Call
:
// Get the method info for GetTime (note the Type[0] signifying no args taken by GetTime);
var methodInfo = typeof(MyClass).GetMethod("GetTime", new Type[0]);
var mCallGetTime = Expression.Call(methodInfo);
GetName
也是如此:
// Get the method info for GetName (note the new[] {typeof(Type)} signifying the arg taken by GetName
var getNameMethodInfo = typeof(MyClass).GetMethod("GetName", new[] { typeof(Type)});
var mCallGetName = Expression.Call(getNameMethodInfo, paramExp);
您的答案的替代方法是创建一个完全通用的方法,该方法将为任何类型的任何通用静态方法构造一个 Func<T>
。
public Func<T> BuildGenericStaticFunc<T>()
{
var type = typeof(T);
return Expression.Lambda<Func<T>>(
Expression
.Call(
type.GetMethod("Create", BindingFlags.Static | BindingFlags.Public)
.MakeGenericMethod(type),
Expression.Constant(type)
))
.Compile();
}
var result = BuildGenericStaticFunc<MyClass>();