Это:
private static IReadOnlyList<Tuple<string, Type>> ParseExpression<T1, T2>(Expression<Func<T1, T2>> func)
{
var par = func.Parameters[0];
var lst = new List<Tuple<string, Type>>();
Expression exp = func.Body;
while (exp != par)
{
if (exp.NodeType != ExpressionType.MemberAccess)
{
throw new Exception(exp.ToString());
}
MemberExpression me = (MemberExpression)exp;
MemberInfo mi = me.Member;
if (mi.MemberType == MemberTypes.Field)
{
FieldInfo fi = (FieldInfo)mi;
lst.Add(Tuple.Create(fi.Name, fi.FieldType));
}
else if (mi.MemberType == MemberTypes.Property)
{
PropertyInfo pi = (PropertyInfo)mi;
lst.Add(Tuple.Create(pi.Name, pi.PropertyType));
}
else
{
throw new Exception(exp.ToString());
}
exp = me.Expression;
}
lst.Reverse();
return lst;
}
Пример:
class Cl1
{
public Cl2 Cl2;
}
class Cl2
{
public string Str { get; set; }
}
и затем:
var result = ParseExpression<Cl1, string>(x => x.Cl2.Str);
foreach (var el in result)
{
Console.WriteLine($"{el.Item1}: {el.Item2}");
}