Очень дешевый способ выглядит так:
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» и делать .ToArray()
в вашем стеке после цикла.
В любом случае, вызовите мой метод, например, DoSomething((DateTime x) => x.TimeOfDay.TotalHours);
.
Более длинный пример вызова: DoSomething((System.Threading.Thread x) => x.CurrentCulture.NumberFormat.NumberDecimalSeparator.Length);
Если вы хотите вернуть Func<,>
равнину, вы используете:
var func = valueGetterExpr.Compile();
var extractedValue = func(_someFields);
Я уверен, что это можно улучшить несколькими способами.