在 C# 中,如何使用反射计算表达式主体输出函数中包含的属性数量?

Posted

技术标签:

【中文标题】在 C# 中,如何使用反射计算表达式主体输出函数中包含的属性数量?【英文标题】:In C#, how do you count the number of properties contained within an expression body output function using reflection? 【发布时间】:2022-01-19 02:49:58 【问题描述】:

以下是包含 ExpandClause 表达式主体的代码块,我想在其上运行计数,并且我想知道结果对象中包含多少属性。 如果可以避免,我宁愿不需要实例化任何这些对象;反思将是首选。 我的用例围绕着一个单元测试,如果在给定的 BaseRepository 的具体实现的 ExpandClause 中包含超过 5 个属性,则该单元测试将失败。

例如,下面的代码应该输出 2,因为 ExpandClause 使用了两个属性,e.Name 和 e.Age。

public class Person

    public int Age  get; set; 

    public string EyeColour  get; set; 

    public int Height  get; set; 

    public string Name  get; set; 


public abstract class BaseRepository<TEntity>

    protected abstract Expression<Func<TEntity, object>>? ExpandClause  get; 


public class PersonRepository : BaseRepository<Person>

    protected override Expression<Func<Person, object>>? ExpandClause =>
        e => new
             
                 e.Name,
                 e.Age
             ;

【问题讨论】:

创建一个派生自ExpressionVisitor的类,覆盖VisitMember (MemberExpression node),调用.Visit(expr) 【参考方案1】:

感谢@Jeremy's comment,我找到了适合我的解决方案。

这个类计算Expression中的成员:

public class ExpandClauseCounterExpressionVisitor : ExpressionVisitor

    public int MemberCount  get; private set; 

    public override Expression Visit(Expression node)
    
        if (node.NodeType == ExpressionType.Lambda)
        
            if (node is not LambdaExpression lambdaExpression)
            
                throw new NullReferenceException(nameof(lambdaExpression));
            

            if (lambdaExpression.Body is not NewExpression newExpression)
            
                throw new NullReferenceException(nameof(newExpression));
            

            MemberCount = newExpression.Members.Count;
        

        return base.Visit(node) ?? throw new NullReferenceException("Cannot visit a null node");
    

这段代码实际上是调用ExpressionVisitor 并执行计数检查:

var personRepository = new PersonRepository();
var expressionVisitor = new ExpandClauseCounterExpressionVisitor();
_ = expressionVisitor.Visit(personRepository.ExpandClause!);
if (expressionVisitor.MemberCount > 5)

    // Do something

【讨论】:

以上是关于在 C# 中,如何使用反射计算表达式主体输出函数中包含的属性数量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在运行时使用反射构建这个 c#“表达式”?

如何在 C# 中使用反射调用具有不同类型参数的方法

如何在R语言中用apply等函数替代for循环

C# 中具有表达式主体的私有成员的标准命名约定是啥[关闭]

C#高级技师语法,你会吗?

C#编程:定义一个函数,计算两个整数相除并输出结果,然后在主函数中调用该函数 来吧,兄弟们!