当多个程序集中的 GraphQL ObjectGraphTypes 时,依赖注入将不起作用
Dependency injection won't work when GraphQL ObjectGraphTypes in multiple assemblies
我在几个项目中定义了几个 GraphQL ObjectGraphType 和查询。所有这些项目都依赖于 asp.net 样板 GraphQL 项目。当我尝试调用任何 graphQL 查询时,它 return 错误 "Castle.MicroKernel.ComponentNotFoundException: "找不到支持该服务的组件。
异常堆栈跟踪
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 都在 asp.net 样板 GraphQL 项目的 1 个项目中时它起作用。
为了允许在多个项目中使用 GraphQL ObjectGraphType 和查询而不是将所有内容都放在 asp.net 样板 GraphQL 项目中,我进行了以下更改:
- 我创建了一个新的 QueryContainer (ExtQueryContainer.cs) 来扩展原来的 QueryContainer.cs
- 为了让新创建的QueryContainer继承原来的QueryContainer,我修改了原来的QueryContainer,去掉了class中的sealed关键字。
- 我创建了一个新的 GraphQL 架构 (GraphQLSchema.cs),它引用了新创建的 ExtQueryContainer
ServiceCollectionExtensions.cs(在 asp.net 样板 GraphQL 项目中)
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>();
}
}
您需要为每个程序集调用 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
我在几个项目中定义了几个 GraphQL ObjectGraphType 和查询。所有这些项目都依赖于 asp.net 样板 GraphQL 项目。当我尝试调用任何 graphQL 查询时,它 return 错误 "Castle.MicroKernel.ComponentNotFoundException: "找不到支持该服务的组件。
异常堆栈跟踪
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 都在 asp.net 样板 GraphQL 项目的 1 个项目中时它起作用。
为了允许在多个项目中使用 GraphQL ObjectGraphType 和查询而不是将所有内容都放在 asp.net 样板 GraphQL 项目中,我进行了以下更改:
- 我创建了一个新的 QueryContainer (ExtQueryContainer.cs) 来扩展原来的 QueryContainer.cs
- 为了让新创建的QueryContainer继承原来的QueryContainer,我修改了原来的QueryContainer,去掉了class中的sealed关键字。
- 我创建了一个新的 GraphQL 架构 (GraphQLSchema.cs),它引用了新创建的 ExtQueryContainer
ServiceCollectionExtensions.cs(在 asp.net 样板 GraphQL 项目中)
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>();
}
}
您需要为每个程序集调用 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