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



下面是一个代码块,包含我想对其运行计数的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
};
}

感谢@Jeremy的评论,我找到了一个适合我的解决方案。

此类计算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
}

最新更新