Graphql-dotnet: Why won't dependency injection work in my Type classes? trying to inject IDataLoaderContextAccessor

Created on 25 Sep 2019  路  3Comments  路  Source: graphql-dotnet/graphql-dotnet

I am using GraphQL.NET 3.5.0-alpha0027 in a asp.net core 2.2 api project

my ConfigureServices is as follows

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        services.AddDbContext<BodySystemContext>();
        services.AddSingleton<IServiceProvider>(c => new FuncServiceProvider(type => c.GetRequiredService(type)));
        services.AddScoped<GraphQLSchema>();
        services.AddGraphQL(o => { o.ExposeExceptions = true; o.EnableMetrics = true; })
            .AddGraphTypes(ServiceLifetime.Scoped)
            .AddDataLoader();
    }

my Configure is as follows

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseGraphQL<GraphQLSchema>();
        app.UseGraphQLPlayground(new GraphQLPlaygroundOptions());
    }

my type class is as follows

public class BodySystemType : ObjectGraphType<BodySystem>
{
    public BodySystemType(IDataLoaderContextAccessor dataLoaderAccessor)
    {
        Field(f => f.Id, type: typeof(IdGraphType));
        Field(f => f.Name);
        Field(f => f.Description, nullable: true);
        Field(f => f.RowVersion, type: typeof(ListGraphType<ByteGraphType>));
        Field<ListGraphType<BodySystemTranslationType>>(
            "BodySystemTranslations",
            resolve: context =>
            {
                var loader =
                    dataLoaderAccessor.Context.GetOrAddCollectionBatchLoader<short, BodySystemTranslation>(
                        "GetBodySystemTranslationByBodySystem", GetBodySystemTranslationByBodySystemId);
                return loader.LoadAsync(context.Source.Id);
            });
    }

    public async Task<ILookup<short, BodySystemTranslation>> GetBodySystemTranslationByBodySystemId(IEnumerable<short> bodySystemIds)
    {
        var bodySystemTranslations = await (new BodySystemContext()).BodySystemTranslation.Where(a => bodySystemIds.Contains(a.BodySystemId)).ToListAsync();
        return bodySystemTranslations.ToLookup(x => x.BodySystemId);
    }
}

my project compiles and runs playground alright but it won't show a schema and when i try to query it fails with error about needing a type with a parameterless constructor

"errors": [
{
"message": "GraphQL.ExecutionError: Failed to call Activator.CreateInstance. Type: Api.GraphQL.Types.BodySystemType ---> System.Exception: Failed to call Activator.CreateInstance. Type: Api.GraphQL.Types.BodySystemType ---> System.MissingMethodException: No parameterless constructor defined for this object.\r\n at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean wrapExceptions, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor)\r\n at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean wrapExceptions, Boolean skipCheckThis, Boolean fillCache)\r\n at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)\r\n at GraphQL.DefaultServiceProvider.GetService(Type serviceType)\r\n --- End of inner exception stack trace ---\r\n at GraphQL.DefaultServiceProvider.GetService(Type serviceType)\r\n at GraphQL.Utilities.ServiceProviderExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)\r\n at GraphQL.Types.Schema.b__59_1(Type type)\r\n at GraphQL.Types.GraphTypesLookup.AddTypeIfNotRegistered(Type type, TypeCollectionContext context)\r\n at GraphQL.Types.GraphTypesLookup.HandleField(Type parentType, FieldType field, TypeCollectionContext context)\r\n at GraphQL.Types.GraphTypesLookup.AddType(IGraphType type, TypeCollectionContext context)\r\n at GraphQL.Types.GraphTypesLookup.Create(IEnumerable1 types, IEnumerable1 directives, Func2 resolveType, IFieldNameConverter fieldNameConverter, Boolean seal)\r\n at GraphQL.Types.Schema.CreateTypesLookup()\r\n at System.Lazy1.ViaFactory(LazyThreadSafetyMode mode)\r\n at System.Lazy1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)\r\n at System.Lazy1.CreateValue()\r\n at GraphQL.Types.Schema.get_AllTypes()\r\n at GraphQL.Instrumentation.FieldMiddlewareBuilder.ApplyTo(ISchema schema)\r\n at GraphQL.DocumentExecuter.ExecuteAsync(ExecutionOptions options)\r\n --- End of inner exception stack trace ---",
"extensions": {
"code": "MISSING_METHOD"
}
}

after some searching i figured that it cannot resolve the IDataLoaderContextAccessor ... is that right ? and if yes how can i solve this ? and how can i use the dataloader IDataLoaderContextAccessor without injection !!!

question

Most helpful comment

How is your Schema defined? Is it setup to inject the IServiceProvider?

public MySchema(IServiceProvider provider)
    : base(provider)
{}

@joemcbride , Actually yes, it was injecting the IServiceProvider but unfortunately it was not passing it to base class, like follows

public MySchema(IServiceProvider provider)
{
}

but after i modified it to pass the IServiceProvider to the base class like you suggested, it now works like a champ ...

Thank you very much, i appreciate the help

All 3 comments

How is your Schema defined? Is it setup to inject the IServiceProvider?

public MySchema(IServiceProvider provider)
    : base(provider)
{}

How is your Schema defined? Is it setup to inject the IServiceProvider?

public MySchema(IServiceProvider provider)
    : base(provider)
{}

@joemcbride , Actually yes, it was injecting the IServiceProvider but unfortunately it was not passing it to base class, like follows

public MySchema(IServiceProvider provider)
{
}

but after i modified it to pass the IServiceProvider to the base class like you suggested, it now works like a champ ...

Thank you very much, i appreciate the help

@Walid-Abdulrazik You can remove this line
c# services.AddSingleton<IServiceProvider>(c => new FuncServiceProvider(type => c.GetRequiredService(type)));

MS DI has builtin support for IServiceProvider

Was this page helpful?
0 / 5 - 0 ratings

Related issues

joemcbride picture joemcbride  路  4Comments

VladimirAkopyan picture VladimirAkopyan  路  4Comments

mahald picture mahald  路  4Comments

tcetin picture tcetin  路  3Comments

wendelnascimento picture wendelnascimento  路  3Comments