我正在开发一个使用lambda表达式来指定属性的API.我正在使用这个与此类似的着名代码(这是简化和不完整的,只是为了说清楚我在说什么):
public void Foo<T, P>(Expression<Func<T, P>> action)
{
var expression = (MemberExpression)action.Body;
string propertyName = expression.Member.Name;
// ...
}
Run Code Online (Sandbox Code Playgroud)
被称为这样:
Foo((String x) => x.Length);
Run Code Online (Sandbox Code Playgroud)
现在我想通过链接属性名来指定属性路径,如下所示:
Foo((MyClass x) => x.Name.Length);
Run Code Online (Sandbox Code Playgroud)
Foo应该能够将路径拆分为其属性名称("Name"和"Length").有没有办法以合理的努力做到这一点?
有一个类似的外观问题,但我认为他们正试图在那里结合lambda表达式.
另一个问题也是处理嵌套的属性名称,但我真的不明白他们在谈论什么.
Luk*_*keH 32
像这样的东西?
public void Foo<T, P>(Expression<Func<T, P>> expr)
{
MemberExpression me;
switch (expr.Body.NodeType)
{
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
var ue = expr.Body as UnaryExpression;
me = ((ue != null) ? ue.Operand : null) as MemberExpression;
break;
default:
me = expr.Body as MemberExpression;
break;
}
while (me != null)
{
string propertyName = me.Member.Name;
Type propertyType = me.Type;
Console.WriteLine(propertyName + ": " + propertyType);
me = me.Expression as MemberExpression;
}
}
Run Code Online (Sandbox Code Playgroud)
Joh*_*son 15
我用ExpressionVisitor玩了一点:
public static class PropertyPath<TSource>
{
public static IReadOnlyList<MemberInfo> Get<TResult>(Expression<Func<TSource, TResult>> expression)
{
var visitor = new PropertyVisitor();
visitor.Visit(expression.Body);
visitor.Path.Reverse();
return visitor.Path;
}
private class PropertyVisitor : ExpressionVisitor
{
internal readonly List<MemberInfo> Path = new List<MemberInfo>();
protected override Expression VisitMember(MemberExpression node)
{
if (!(node.Member is PropertyInfo))
{
throw new ArgumentException("The path can only contain properties", nameof(node));
}
this.Path.Add(node.Member);
return base.VisitMember(node);
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
var path = string.Join(".", PropertyPath<string>.Get(x => x.Length).Select(p => p.Name));
Run Code Online (Sandbox Code Playgroud)
asg*_*las 13
老问题,我知道......但如果它只是你需要的名字,更简单的方法是:
expr.ToString().Split('.').Skip(1)
Run Code Online (Sandbox Code Playgroud)
编辑:
public class A
{
public B Property { get; set; }
}
public class B
{
public C field;
}
[Fact]
public void FactMethodName()
{
var exp = (Expression<Func<A, object>>) (x => x.Property.field);
foreach (var part in exp.ToString().Split('.').Skip(1))
Console.WriteLine(part);
// Output:
// Property
// field
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8796 次 |
| 最近记录: |