GraphQL.NET relies a lot on DI containers to get instances for certain graph types. At first it might be a bit daunting to come across an error along the likes of this:
GraphQL.ExecutionError: No service for type '...' has been registered.
It is GraphQL’s way of telling the world that it could not find an instance of a certain type in the DI container.
The usual way to solve this problem is to register a new instance with the DI container which usually goes like this:
It works. But for large GraphQL api’s it doesn’t scale well, and it’s annoying for the developers to be remembered to register types with the DI container everytime a new type has been added.
Due to habit I tend to cluster the same types of classes together in the same folder/namespace.
My folder structure looks a bit like this:
Graph |- Types |- Enum |- Input |- Interface |- Object
The nice thing about this is that all different types of
ObjectGraphType derivatives are stored in the
Graph.Types namespace, while also having a distinction between the several subtypes.
Now in order to solve the registration problem for once and for all you can add the following code block to the place where you usually register your graph types.
Assembly .GetExecutingAssembly() .GetTypes() .Where(q => q.IsClass && (q.Namespace?.StartsWith("Graph.Types") ?? false)) .ToList() .ForEach(type => services.AddSingleton(type));
The code shown above invokes some reflection magic to retrieve all classes in the executing assembly (which in my case is also the assembly in which I have defined the graph types), filter them for the namespace, which is supplied as string, and add them to the DI container.
The only thing you need to do is to replace the namespace, and verify whether you pull your metadata from the correct assembly.
Use of reflection is being scrutinized because it is ‘slow’ and there are usually better alternatives. In this case it will lead to more maintainable code, and it is only ran during startup either way ¯\_(ツ)_/¯
👉 Do you like what I'm writing? Sign up to receive new content straight into your mailbox!