为了提高效率,在 Joe McBride 的提示下,我选择基于 GraphQL-dotnet EnterLeaveListener 源创建自己的 MyEnterLeaveListener。
public class EnterLeaveListenerState
{
public OperationType OperationType { get; private set; }
public string CurrentFieldPath { get; private set; }
}
public class MyEnterLeaveListener : INodeVisitor, IEventSource<IEnterLeaveListenerEventSink>
{
....
public void Enter(INode node)
{
var isField = TypeHelper<Field>.IsType(node.GetType());
var isOperation = TypeHelper<Operation>.IsType(node.GetType());
if (isOperation)
{
var operation = node as Operation;
OperationType = operation.OperationType;
RunningPath.Clear();
FireEnterLeaveListenerState(new EnterLeaveListenerState(OperationType, CurrentFieldPath));
}
if (isField)
{
var field = node as Field;
var next = CurrentFieldPath + "/" + field.Name;
RunningPath.Push(next);
FireEnterLeaveListenerState(new EnterLeaveListenerState(OperationType, CurrentFieldPath));
}
_listeners
.Where(l => l.Enter != null && l.Matches(node))
.Apply(l => l.Enter(node));
}
public void Leave(INode node)
{
var isField = TypeHelper<Field>.IsType(node.GetType());
if (isField)
{
var field = node as Field;
RunningPath.Pop();
FireEnterLeaveListenerState(new EnterLeaveListenerState(OperationType, CurrentFieldPath));
}
_listeners
.Where(l => l.Leave != null && l.Matches(node))
.Apply(l => l.Leave(node));
}
....
}
我一边走一边构建操作和路径,并提出任何变化。