表达式 Lambda Func 到 c# 中的字符串
Expression Lambda Func to string in c#
我想获取 lambda Func<> Expression 的字符串表示形式以获取 属性 路径。我有这个例子
Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses["Address"];
我期待一个字符串
"EmployeeInfo.Addresses["Address"]"
当我做 _xxx.ToString(); 时,我将只做一些字符串解析,我可以得到上面的结果。
我的问题是什么时候做
var _addrName = "Address";
Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses[_addrName];
我得到了一个很长的字符串
"EmployeeInfo.Addresses.get_Item(value(UnitTestProj.UnitTest.AnyTest+<>c__DisplayClass0)._addr)"
这是很难想出的
"EmployeeInfo.Addresses["地址"]"
有什么办法可以达到我的目的吗?
TIA
这应该会让你走得更远 - 它很老套,但我认为没有办法解决它:
Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses[address];
WriteLine(ExprToString(_xxx)); //e.EmployeeInfo.Addresses[address]
_xxx = x => x.EmployeeInfo.Addresses["XYZ"];
WriteLine(ExprToString(_xxx)); //x.EmployeeInfo.Addresses["XYZ"]
_xxx = y => y.EmployeeInfo.Addresses[null];
WriteLine(ExprToString(_xxx)); //y.EmployeeInfo.Addresses[null]
_xxx = z => z.EmployeeInfo.Name;
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.Name
_xxx = z => z.EmployeeInfo.GetSalary();
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.GetSalary()
_xxx = z => z.EmployeeInfo.Addresses.Select(a => a.Street);
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.Addresses.Select(a.Street)
_xxx = z => z.EmployeeInfo.Array[3];
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.Array[3]
实施:
static string ExprToString(Expression expr)
{
switch (expr.NodeType)
{
case ExpressionType.Lambda:
//x => (Something), return only (Something), the Body
return ExprToString(((LambdaExpression) expr).Body);
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
//type casts are not important
return ExprToString(((UnaryExpression) expr).Operand);
case ExpressionType.Call:
//method call can be an Indexer (get_Item),
var callExpr = (MethodCallExpression) expr;
if (callExpr.Method.Name == "get_Item")
{
//indexer call
return ExprToString(callExpr.Object) + "[" + string.Join(",", callExpr.Arguments.Select(ExprToString)) + "]";
}
else
{
//method call
var arguments = callExpr.Arguments.Select(ExprToString).ToArray();
string target;
if (callExpr.Method.IsDefined(typeof (ExtensionAttribute), false))
{
//extension method
target = string.Join(".", arguments[0], callExpr.Method.Name);
arguments = arguments.Skip(1).ToArray();
}
else if (callExpr.Object == null)
{
//static method
target = callExpr.Method.Name;
}
else
{
//instance method
target = string.Join(".", ExprToString(callExpr.Object), callExpr.Method.Name);
}
return target + "(" + string.Join(",", arguments) + ")";
}
case ExpressionType.MemberAccess:
//property or field access
var memberExpr = (MemberExpression) expr;
if (memberExpr.Expression.Type.Name.Contains("<>")) //closure type, don't show it.
{
return memberExpr.Member.Name;
}
else
{
return string.Join(".", ExprToString(memberExpr.Expression), memberExpr.Member.Name);
}
}
//by default, show the standard implementation
return expr.ToString();
}
我想获取 lambda Func<> Expression 的字符串表示形式以获取 属性 路径。我有这个例子
Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses["Address"];
我期待一个字符串
"EmployeeInfo.Addresses["Address"]"
当我做 _xxx.ToString(); 时,我将只做一些字符串解析,我可以得到上面的结果。
我的问题是什么时候做
var _addrName = "Address";
Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses[_addrName];
我得到了一个很长的字符串
"EmployeeInfo.Addresses.get_Item(value(UnitTestProj.UnitTest.AnyTest+<>c__DisplayClass0)._addr)"
这是很难想出的 "EmployeeInfo.Addresses["地址"]"
有什么办法可以达到我的目的吗?
TIA
这应该会让你走得更远 - 它很老套,但我认为没有办法解决它:
Expression<Func<Employee, object>> _xxx = e => e.EmployeeInfo.Addresses[address];
WriteLine(ExprToString(_xxx)); //e.EmployeeInfo.Addresses[address]
_xxx = x => x.EmployeeInfo.Addresses["XYZ"];
WriteLine(ExprToString(_xxx)); //x.EmployeeInfo.Addresses["XYZ"]
_xxx = y => y.EmployeeInfo.Addresses[null];
WriteLine(ExprToString(_xxx)); //y.EmployeeInfo.Addresses[null]
_xxx = z => z.EmployeeInfo.Name;
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.Name
_xxx = z => z.EmployeeInfo.GetSalary();
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.GetSalary()
_xxx = z => z.EmployeeInfo.Addresses.Select(a => a.Street);
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.Addresses.Select(a.Street)
_xxx = z => z.EmployeeInfo.Array[3];
WriteLine(ExprToString(_xxx)); //z.EmployeeInfo.Array[3]
实施:
static string ExprToString(Expression expr)
{
switch (expr.NodeType)
{
case ExpressionType.Lambda:
//x => (Something), return only (Something), the Body
return ExprToString(((LambdaExpression) expr).Body);
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
//type casts are not important
return ExprToString(((UnaryExpression) expr).Operand);
case ExpressionType.Call:
//method call can be an Indexer (get_Item),
var callExpr = (MethodCallExpression) expr;
if (callExpr.Method.Name == "get_Item")
{
//indexer call
return ExprToString(callExpr.Object) + "[" + string.Join(",", callExpr.Arguments.Select(ExprToString)) + "]";
}
else
{
//method call
var arguments = callExpr.Arguments.Select(ExprToString).ToArray();
string target;
if (callExpr.Method.IsDefined(typeof (ExtensionAttribute), false))
{
//extension method
target = string.Join(".", arguments[0], callExpr.Method.Name);
arguments = arguments.Skip(1).ToArray();
}
else if (callExpr.Object == null)
{
//static method
target = callExpr.Method.Name;
}
else
{
//instance method
target = string.Join(".", ExprToString(callExpr.Object), callExpr.Method.Name);
}
return target + "(" + string.Join(",", arguments) + ")";
}
case ExpressionType.MemberAccess:
//property or field access
var memberExpr = (MemberExpression) expr;
if (memberExpr.Expression.Type.Name.Contains("<>")) //closure type, don't show it.
{
return memberExpr.Member.Name;
}
else
{
return string.Join(".", ExprToString(memberExpr.Expression), memberExpr.Member.Name);
}
}
//by default, show the standard implementation
return expr.ToString();
}