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