v0.8.0 Upgrade Guide

Please report any issues you find with this new behavior.

Abstract Syntax Tree

The core language types have been updated to more closely represent the Abstract Syntax Tree of GraphQL. This allows for the ability to "walk" the tree of the graph. The language types implement INode, which looks like:

public interface INode
{
    IEnumerable<INode> Children { get; }

    SourceLocation SourceLocation { get; }

    bool IsEqualTo(INode node);
}
  • Children is a list of child nodes, such as a SelectionSet.
  • SourceLocation contains the line/number of where the node is in the source operation.

Note: Selections has been renamed to SelectionSet and is now an INode.

You can walk the graph with a simple visitor such as BasicVisitor. An INodeVisitor is passed to the BasicVisitor which will walk the node graph and sequentially call Enter and Leave on each INodeVisitor with the current INode.

public void VisitDocument(string operation)
{
    var builder = new AntlrDocumentBuilder();
    var document = builder.Build(operation);

    var debugVisitor = new DebugNodeVisitor();
    var basicVisitor = new BasicVisitor(new[] {debugVisitor});
    basicVisitor.Visit(document);
}

public class DebugNodeVisitor : INodeVisitor
{
    public void Enter(INode node)
    {
        Debug.WriteLine($"Entering {node}");
    }

    public void Leave(INode node)
    {
        Debug.WriteLine($"Leaving {node}");
    }
}

You can also use funcs to make matching a particular INode easy:


new NodeVisitorMatchFuncListener<Field>(
    n => n is Field,
    field =>
    {
      // do something with the field
    }
);

public class NodeVisitorMatchFuncListener<T> : INodeVisitor
    where T : INode
{
    private readonly Func<INode, bool> _match;
    private readonly Action<T> _action;

    public NodeVisitorMatchFuncListener(Func<INode, bool> match, Action<T> action)
    {
        _match = match;
        _action = action;
    }

    public void Enter(INode node)
    {
        if (_match(node))
        {
            _action((T) node);
        }
    }

    public void Leave(INode node)
    {
    }
}

Additional updates and changes will most likely be coming to the AST as more validation rules are implemented, however they should not be as drastic.

Scalars

Coerce has been removed and has been replaced by ParseValue, ParseLiteral, and Serialize.

  • ParseValue - This should contain the logic previously found in Coerce.
  • ParseLiteral - This takes in an AST IValue that should be converted to a real value. StringValue, IntValue, LongValue, FloatValue, EnumValue, ListValue, ObjectValue.
  • Serialize - The value to output.

An example from FloatGraphType:

public class FloatGraphType : ScalarGraphType
{
    public FloatGraphType()
    {
        Name = "Float";
    }

    public override object Serialize(object value)
    {
        return ParseValue(value);
    }

    public override object ParseValue(object value)
    {
        double result;
        if (double.TryParse(value?.ToString() ?? string.Empty, out result))
        {
            return result;
        }
        return null;
    }

    public override object ParseLiteral(IValue value)
    {
        var floatVal = value as FloatValue;
        return floatVal?.Value;
    }
}