問題は、ここには強力な型付けサポートがないため、式ツリーを利用することさえできないことです。ただし、DynamicLinqは既にこれを行っているため、いくつかの変更を加えるだけで簡単に機能させることができます。この機能を追加するには、DynamicExpression クラスに独自の静的メソッドをいくつか作成するだけです。
public static Expression<Func<T, S>> ParseLambda<T, S>(string expression)
{
string paramString = expression.Substring(0, expression.IndexOf("=>")).Trim();
string lambdaString = expression.Substring(expression.IndexOf("=>") + 2).Trim();
ParameterExpression param = Expression.Parameter(typeof(T), paramString);
return (Expression<Func<T,S>>)ParseLambda(new[] { param }, typeof(S), lambdaString, null);
}
public static LambdaExpression ParseLambda(string expression, Type returnType, params Type[] paramTypes)
{
string paramString = expression.Substring(0, expression.IndexOf("=>")).Trim("() ".ToCharArray());
string lambdaString = expression.Substring(expression.IndexOf("=>") + 2).Trim();
var paramList = paramString.Split(',');
if (paramList.Length != paramTypes.Length)
throw new ArgumentException("Specified number of lambda parameters do not match the number of parameter types!", "expression");
List<ParameterExpression> parameters = new List<ParameterExpression>();
for (int i = 0; i < paramList.Length; i++)
parameters.Add(Expression.Parameter(paramTypes[i], paramList[i].Trim()));
return ParseLambda(parameters.ToArray(), returnType, lambdaString, null);
}
両方の使用法:
Func<string, string> func = DynamicExpression.ParseLambda<string, string>("f => f.Substring(0, f.IndexOf(\" \"))").Compile();
Func<string, int, string> otherFunc = ((Expression<Func<string, int, string>>)DynamicExpression.ParseLambda("(str, ind) => (ind * 100).ToString() + str")).Compile();
編集:これは完全にテストされていないため、いくつかの単体テストでこれらが正しい結果を生成することを確認することをお勧めします。メソッドで使用するパラメーターを明示的に宣言するだけで、過度に複雑なことはしていませんpublic static LambdaExpression ParseLambda(ParameterExpression[] parameters, Type resultType, string expression, params object[] values)
。
また、@Mauro Destro によって指摘されたparamList
、ParameterExpression
.