将给定的属性访问权限转换为链接字符串



我正试图编写一个扩展方法来从给定的LambdaExpression中检索属性路径。

我希望能够像一样称呼它

var路径=((事件e(=>e.Address.City.Name(.ToChainedPath((;

它将返回Address.City.Name作为由.分隔的string

目前我的分机看起来像这个

public static string ToChainedPath<TSource, TProperty>(this Expression<Func<TSource, TProperty>> expr, char separator = '.')
{
MemberExpression me;
switch (expr.Body.NodeType)
{
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
var ue = expr.Body as UnaryExpression;
me = ue?.Operand as MemberExpression;
break;
default:
me = expr.Body as MemberExpression;
break;
}
var propertyNames = new List<string>();
while (me != null)
{
propertyNames.Add(me.Member.Name);
me = me.Expression as MemberExpression;
}
propertyNames.Reverse();
return string.Join(separator, propertyNames);
}

像一样使用时效果良好

Expression<Func<Event, string>> expression = e => e.Address.City.Name;
var propertyChain = expression.ToChainedPath();

但这不适用于我想要的,因为(Event e) => e.Address.City.NameFunc<Event, string>而不是Expression<Func<Event,string>>。我已经尝试将Func转换为Expression,但到目前为止没有任何帮助。

我还将扩展更改为扩展Func而不是Expression,但随后我松开了Body

这样做可能吗?

lambda表达式本身没有类型(请参阅规范(,因此如果只执行以下操作,编译器将不知道在哪里可以找到ToChainedPath

((Event e) => e.Address.City.Name).ToChainedPath();

您没有给它任何关于lambda表达式应该转换为什么的类型信息(委托类型?表达式类型?(。因此,这种确切的语法是不可能的。

可以提供类型信息的另一种方法是使用方法参数。

EnclosingClass.GetChainedPath(e => e.Address.City.Name);

如果编译器能够解析GetChainedPath是什么,它将知道它有一个类型为Expression<Func<Event, string>>:的参数

public static string GetChainedPath<TSource, TProperty>(Expression<Func<TSource, TProperty>> expr, char separator = '.')

因此它知道lambda应该转换成什么类型

如果你想让它更加简洁(省略EnclosingClass.(,你可以为GetChainedPath做一个using static

using static YourNamespace.EnclosingClass;

最新更新