处理 MemberExpression 中的 "convert to object"

Dealing with "convert to object" in a MemberExpression

我有一个 class 看起来像这样:

public class MyClass
{
  public int Id { get; set; }
  public string Name { get; set; }
}

我需要这样做:

var memberExpressions = ConvertToMemberExpressions<MyClass>(o => o.Id, o => o.Name);

...

public static List<MemberExpression> ConvertToMemberExpressions<T>(params Expression<Func<T, object>>[] methodExpressions)
{
    var results = new List<MemberExpression>();
    foreach(var methodExpression in methodExpressions)
    {
        var memberExpression = methodExpression.Body as MemberExpression;
        results.Add(memberExpression);
    }
    return results;
}

问题是,由于 Func<T, object>(能够同时包含 intstring 作为参数),我的方法表达式看起来像这样:{o => Convert(o.Id, Object)},其中不是我需要的。我需要达到 o.Id.

字符串不会发生这种情况:{o => o.Name},此处没有转换。

我使用 Func<T,object> 是为了能够利用 Intellisense 并到达 MyClass 的道具。我试过使用 Func<T, dynamic>,但结果是一样的。

可以使用多个重载来解决:

public static ConvertToMemberExpressions<TClass, T1>(Expression<Func<TClass,T1>>[] methodExpression1)
public static ConvertToMemberExpressions<TClass, T1, T2>(Expression<Func<TClass,T1>>[] methodExpression1, Expression<Func<TClass,T2>>[] methodExpression2)
...

...但这是我想尽可能避免的牺牲。


问题:

是否可以从 o => Convert(o.Id, Object) 构建 o => o.Id

只需检查您的 methodExpression.Body 是否为 UnaryExpressionNodeTypeConvert:

public static List<MemberExpression> ConvertToMemberExpressions<T>(params Expression<Func<T, object>>[] methodExpressions)
{
    var results = new List<MemberExpression>();
    foreach (var methodExpression in methodExpressions)
    {
        var expr = methodExpression.Body;
        if (expr is UnaryExpression unaryExpression && unaryExpression.NodeType == ExpressionType.Convert)
        {
            expr = unaryExpression.Operand;
        }

        if (expr is MemberExpression memberExpression)
        {
            results.Add(memberExpression);
        }
        else
        {
            throw new ArgumentException($"Unexpected expression type {expr.NodeType}");
        }
    }
    return results;
}

使用表达式时,调试器是你的朋友: