假设我有以下代码:
public void DoSomething<TU,TV>(Func<TU,TV> valueGetter)
{
TV extractedValue = valueGetter(_someFields);
//Here, how to get from valueGetter the properties used to get the value.
PropertyInfo[] properties = ....;//["SubObject", "SubSubObject", "Property"]
}
DoSomething((x)=>x.SubObject.SubSubObject.Property)//Let admit that this path always contains only properties, never methods
我也想提取一个PropertyInfo数组,其中包含路径中的每个属性以通过反射获取对象。
有可能吗?
答案 0 :(得分:1)
非常便宜的方式是这样的:
public void DoSomething<TU, TV>(Expression<Func<TU, TV>> valueGetterExpr)
{
var str = valueGetterExpr.ToString();
// now 'str' holds string representation of the lambda expression
}
更具结构性的方法与此类似:
public void DoSomething<TU, TV>(Expression<Func<TU, TV>> valueGetterExpr)
{
var expr = valueGetterExpr.Body;
var li = new List<PropertyInfo>();
while (!(expr is ParameterExpression))
{
if (!(expr is MemberExpression me))
throw new Exception("Unexpected kind");
if (!(me.Member is PropertyInfo pi))
throw new Exception("Unexpected kind");
li.Add(pi);
expr = me.Expression;
}
// now 'li' holds all the properties
}
与您所说的相反,顺序相反。您可以使用List<>
将li.Reverse();
颠倒过来,或者可以使用new Stack<...>()
代替new List<...>()
,使用“ push”代替“ add”,然后执行{{ 1}}在循环后的堆栈上。
无论哪种情况,都可以通过调用我的方法.ToArray()
。
更长的示例调用:DoSomething((DateTime x) => x.TimeOfDay.TotalHours);
如果您想找回普通的DoSomething((System.Threading.Thread x) => x.CurrentCulture.NumberFormat.NumberDecimalSeparator.Length);
,请使用:
Func<,>
我确信可以通过多种方式对此进行改进。
答案 1 :(得分:0)
有可能,但是您需要继续使用ExpressionTree
,而不仅仅是一个func。请从我们心爱的Microsoft网站上查看官方documentation。实际上,这需要大量的反思,所以如果必须要有性能,那就不要这样做。在这种情况下,您必须将更多信息发送到您的方法中,例如元组(function, metadata)
。