Внедрение зависимостей не будет работать, если GraphQL OjectGraphTypes в нескольких сборках

Я определил несколько GraphQL ObjectGraphType и запросов в нескольких проектах. Все эти проекты зависят от стандартного проекта GraphQL asp.net. Он возвращает ошибку "Castle.MicroKernel.ComponentNotFoundException: " Компонент для поддержки службы не найден ", когда я пытался вызвать любые запросы graphQL.

Исключение Stacktrace

Sample.Types.ProductPagedResultGraphType was found ---> Castle.MicroKernel.ComponentNotFoundException: No component for supporting the service Sample.Types.ProductPagedResultGraphType was found
   at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, Arguments arguments, IReleasePolicy policy, Boolean ignoreParentContext)
   at Castle.Windsor.MsDependencyInjection.ScopedWindsorServiceProvider.GetServiceInternal(Type serviceType, Boolean isOptional) in D:\Github\castle-windsor-ms-adapter\src\Castle.Windsor.MsDependencyInjection\ScopedWindsorServiceProvider.cs:line 55
   at GraphQL.Types.Schema.<CreateTypesLookup>b__56_2(Type type)
   at GraphQL.Types.GraphTypesLookup.AddTypeIfNotRegistered(Type type, TypeCollectionContext context)
   at GraphQL.Types.GraphTypesLookup.HandleField(Type parentType, FieldType field, TypeCollectionContext context)
   at GraphQL.Types.GraphTypesLookup.AddType(IGraphType type, TypeCollectionContext context)
   at GraphQL.Types.GraphTypesLookup.Create(IEnumerable`1 types, IEnumerable`1 directives, Func`2 resolveType, IFieldNameConverter fieldNameConverter)
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at GraphQL.Types.Schema.get_AllTypes()
   at GraphQL.Instrumentation.FieldMiddlewareBuilder.ApplyTo(ISchema schema)
   at GraphQL.DocumentExecuter.ExecuteAsync(ExecutionOptions options)
   --- End of inner exception stack trace ---

Он работает, когда все эти запросы и ObjectGraphType находятся в 1 проекте, который является шаблонным проектом GraphQL asp.net.

Чтобы разрешить GraphQL ObjectGraphType и запросы в нескольких проектах вместо помещения всех в стандартный проект GraphQL asp.net, я внес следующие изменения:

  1. Я создал новый QueryContainer (ExtQueryContainer.cs), чтобы расширить исходный QueryContainer.cs
  2. Я изменил исходный QueryContainer, удалив ключевое слово sealed из класса, чтобы позволить вновь созданному QueryContainer унаследовать исходный QueryContainer.
  3. Я создал новую схему GraphQL (GraphQLSchema.cs), которая ссылается на недавно созданный ExtQueryContainer

ServiceCollectionExtensions.cs (в стандартном проекте GraphQL asp.net)

public static class ServiceCollectionExtensions
{
    public static void AddAndConfigureGraphQL(this IServiceCollection services)
    {
        services.AddScoped<IDependencyResolver>(
            x => new FuncDependencyResolver(x.GetRequiredService)
        );

        services
            .AddGraphQL(x => { x.ExposeExceptions = DebugHelper.IsDebug; })
            .AddGraphTypes(ServiceLifetime.Scoped)
            .AddUserContextBuilder(httpContext => httpContext.User)
            .AddDataLoader();
    }
}

ExtQueryContainer.cs

public sealed class ExtQueryContainer : QueryContainer
{
    public QueryContainer(RoleQuery roleQuery, UserQuery userQuery, OrganizationUnitQuery organizationUnitQuery, ProductQuery productQuery)
        : base(roleQuery, userQuery, organizationUnitQuery)
    {
        AddField(productQuery.GetFieldType());
    }
}

GraphQLSchema.cs

public class GraphQLSchema : Schema, ITransientDependency
{
    public GraphQLSchema(IDependencyResolver resolver) : base(resolver)
    {
        Query = resolver.Resolve<ExtQueryContainer>();
    }
}

1 ответ

Решение

Вам нужно позвонить AddGraphTypes для каждой сборки:

var productGraphAssembly = Assembly.GetAssembly(typeof(ProductPagedResultGraphType));

services
    .AddGraphQL(x => { x.ExposeExceptions = DebugHelper.IsDebug; })
    .AddGraphTypes(ServiceLifetime.Scoped) // Assembly.GetCallingAssembly() is implicit
    .AddGraphTypes(productGraphAssembly, ServiceLifetime.Scoped) // Add this
    .AddUserContextBuilder(httpContext => httpContext.User)
    .AddDataLoader();

Вы можете зарегистрироваться IGraphType типы отдельно:

var assembly = Assembly.GetAssembly(typeof(ProductPagedResultGraphType));

foreach (var type in assembly.GetTypes()
    .Where(x => !x.IsAbstract && typeof(IGraphType).IsAssignableFrom(x)))
{
    services.TryAdd(new ServiceDescriptor(type, type, ServiceLifetime.Scoped));
}

Ссылка: https://github.com/graphql-dotnet/server/blob/3.4/src/Core/GraphQLBuilderExtensions.cs

Другие вопросы по тегам