0
votes

So we have a document database which stores our data as XML files. A new requirement is to create a graphQL interface to access the xmldocument. I have implemented the graphQL interface with extensions:

https://github.com/graphql-dotnet/graphql-dotnet https://github.com/graphql-dotnet/server

So far I can create the fields dynamically from the XML file:

public ReferenceType(IRepository repository)
{
    var searchResult = repository.GetExampleForSchema();

    foreach(var field in searchResult.Root.Elements())
    {
        if (!field.HasElements && field.Attribute(json + "Array") == null)
        {
            Field<StringGraphType>(field.Name.LocalName);
        }
        else
        {
            //TODO: Create child ObjectGraphTypes
        }
    }
}

But I can't find out how to return the result in my repository:

public dynamic Search()
{
    var searchResult = new ExpandoObject() as IDictionary<string, object>;
    //var searchResult = new { recordCount = 124345};
    var xDocSearch = InternalSearch();
    foreach (var field in xDocSearch.Root.Elements())
    {
        if (!field.HasElements && field.Attribute(json + "Array") == null)
        {
            var fieldName = field.Name.LocalName;
            searchResult[fieldName] = field.Value;
        }
        else
        {
            //TODO: Create child objects
        }
    }
    return searchResult;
}

The issue is, that GraphQL works with Reflection and uses this logic to read the field: https://github.com/graphql-dotnet/graphql-dotnet/blob/master/src/GraphQL/Resolvers/NameFieldResolver.cs

The ExpandoObject does not have my example recordCount as a property. When I create an anonymous type (see the commented line) it works.

So my questions are:

  1. Is there a possibility to create a type with dynamic properties which can be accessed by reflections? (Can't influence how the value is read)

  2. Is there maybe another way in the GraphQL Extension to solve this issue? Can I configure how the value is read?

Looking forward to some hints and tips!

Thanks, Michael

1

1 Answers

0
votes

So after some research and trying around I could solve it by myself:

It is possible to provide a resolve method for each field:

if (!field.HasElements && field.Attribute(json + "Array") == null)
{
    Field<StringGraphType>(field.Name.LocalName, **resolve: ResolveXml**);
}

and in this method you can do what you want:

public object ResolveXml(ResolveFieldContext<object> context)
{
    var source = (IDictionary<string, object>)context.Source;

    return source[context.FieldName];
}

This is now only the first working solution, of course it might make more sense to return in the repository directly the XDocument and then resolve it here...

Maybe it helps someone as well!