Autofac.Core.Registration.ComponentNotRegisteredException
Autofac.Core.Registration.ComponentNotRegisteredException
我正在尝试对我的应用实施 CQRS 模式。所以我找到了如何从这里的程序集注册所有命令处理程序:Autofac resolve dependency in CQRS CommandDispatcher
但它对我来说效果不佳。这是代码:
containerBuilder.RegisterAssemblyTypes(assembly)
.AsClosedTypesOf(typeof(ICommandHandler<>));
containerBuilder.RegisterAssemblyTypes(assembly)
.AsClosedTypesOf(typeof(IQueryHandler<,>));
处理程序工厂
public class CqrsHandlerFactory : ICqrsHandlerFactory
{
private readonly IContainer container;
public CqrsHandlerFactory(IContainer container)
{
this.container = container;
}
public ICommandHandler<TCommand> GetCommandHandler<TCommand>(TCommand command) where TCommand : class, ICommand
{
return container.Resolve<ICommandHandler<TCommand>>();
}
public IQueryHandler<TQuery, object> GetQueryHandler<TQuery>(TQuery query) where TQuery : class, IQuery
{
return container.Resolve<IQueryHandler<TQuery, object>>();
}
}
公交车
public class CqrsBus : ICqrsBus
{
private readonly ICqrsHandlerFactory cqrsHandlerFactory;
public CqrsBus(ICqrsHandlerFactory cqrsHandlerFactory)
{
this.cqrsHandlerFactory = cqrsHandlerFactory;
}
public void ExecuteCommand(ICommand command)
{
var handler = cqrsHandlerFactory.GetCommandHandler(command);
if (handler == null)
throw new NotImplementedHandlerException(string.Format("Cannot find handler for {0}", command.GetType()));
handler.Handle(command);
}
public TResult RunQuery<TResult>(IQuery query)
{
var handler = cqrsHandlerFactory.GetQueryHandler(query);
if (handler == null)
throw new NotImplementedHandlerException(string.Format("Cannot find handler for {0}", query.GetType()));
return (TResult)handler.Handle(query);
}
}
异常
An exception of type 'Autofac.Core.Registration.ComponentNotRegisteredException' occurred in Autofac.dll but was not handled in user code
Additional information: The requested service 'PromocjeWsieciowkach.Messaging.Core.ICommandHandler`1[[PromocjeWsieciowkach.Messaging.Core.ICommand, PromocjeWsieciowkach.Messaging.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
堆栈跟踪
at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable1 parameters)
at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable
1 parameters)
at PromocjeWsieciowkach.Messaging.Factories.CqrsHandlerFactory.GetCommandHandler[TCommand](TCommand command) in C:\Users\Daniel\Desktop\PromocjeWsieciowkach\src\PromocjeWsieciowkach.Messaging\Factories\CqrsHandlersFactory.cs:line 17
at PromocjeWsieciowkach.Messaging.Bus.CqrsBus.ExecuteCommand(ICommand command) in C:\Users\Daniel\Desktop\PromocjeWsieciowkach\src\PromocjeWsieciowkach.Messaging\Bus\CqrsBus.cs:line 17
at PromocjeWsieciowkach.Controllers.PostController.Index() in C:\Users\Daniel\Desktop\PromocjeWsieciowkach\src\PromocjeWsieciowkach\Controllers\PostController.cs:line 20
at lambda_method(Closure , Object , Object[] )
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__28.MoveNext()
所以我做错了什么?
您的代码和异常消息清楚地表明了问题。总之,您的异常消息说明:
The requested service 'ICommandHandler<ICommand>' has not been registered.
换句话说,您请求的是 ICommandHandler<ICommand>
而不是 ICommandHandler<TestCommand>
。这可以在这里看到:
public void ExecuteCommand(ICommand command)
{
var handler = cqrsHandlerFactory.GetCommandHandler(command);
// ...
}
C# 编译器将类型推断应用于 GetCommandHandler<T>
调用。所以下面的代码才是真正的调用:
var handler = cqrsHandlerFactory.GetCommandHandler<ICommand>(command);
您应该将 ICrqsBus.ExecuteCommand
方法更改为以下内容:
public void ExecuteCommand<TCommand>(TCommand command)
{
// You can merge the factory and your CqrsBus. Splitting them is useless.
var handler = cqrsHandlerFactory.GetCommandHandler<TCommand>();
// You don't need then null check; Autofac never returns null.
handler.Handle(command);
}
如果你不能使 ExecuteCommand
方法通用(例如,因为你不知道编译时的命令类型),你应该使用反射 API 构建通用类型作为如下:
public class CqrsBus : ICqrsBus
{
private readonly IComponentContext context;
public CqrsBus(IComponentContext context)
{
this.context = context;
}
public void ExecuteCommand(ICommand command)
{
Type handlerType = typeof(ICommandHandler<>).MakeGenericType(command.GetType());
dynamic handler = this.context.Resolve(handlerType);
void handler.Execute((dynamic)command);
}
}
同样值得注意的是,如果您使用 nopcommerce 并添加服务,如果您忘记在依赖注册器中添加服务,则会生成相同的错误。
builder.RegisterType<YourService>().As<IYourService>().InstancePerLifetimeScope();
我自己刚遇到这个,下面引用:
The requested service 'ICommandHandler' has not been registered."
让我了解依赖注册商。
谢谢史蒂文
我正在尝试对我的应用实施 CQRS 模式。所以我找到了如何从这里的程序集注册所有命令处理程序:Autofac resolve dependency in CQRS CommandDispatcher
但它对我来说效果不佳。这是代码:
containerBuilder.RegisterAssemblyTypes(assembly)
.AsClosedTypesOf(typeof(ICommandHandler<>));
containerBuilder.RegisterAssemblyTypes(assembly)
.AsClosedTypesOf(typeof(IQueryHandler<,>));
处理程序工厂
public class CqrsHandlerFactory : ICqrsHandlerFactory
{
private readonly IContainer container;
public CqrsHandlerFactory(IContainer container)
{
this.container = container;
}
public ICommandHandler<TCommand> GetCommandHandler<TCommand>(TCommand command) where TCommand : class, ICommand
{
return container.Resolve<ICommandHandler<TCommand>>();
}
public IQueryHandler<TQuery, object> GetQueryHandler<TQuery>(TQuery query) where TQuery : class, IQuery
{
return container.Resolve<IQueryHandler<TQuery, object>>();
}
}
公交车
public class CqrsBus : ICqrsBus
{
private readonly ICqrsHandlerFactory cqrsHandlerFactory;
public CqrsBus(ICqrsHandlerFactory cqrsHandlerFactory)
{
this.cqrsHandlerFactory = cqrsHandlerFactory;
}
public void ExecuteCommand(ICommand command)
{
var handler = cqrsHandlerFactory.GetCommandHandler(command);
if (handler == null)
throw new NotImplementedHandlerException(string.Format("Cannot find handler for {0}", command.GetType()));
handler.Handle(command);
}
public TResult RunQuery<TResult>(IQuery query)
{
var handler = cqrsHandlerFactory.GetQueryHandler(query);
if (handler == null)
throw new NotImplementedHandlerException(string.Format("Cannot find handler for {0}", query.GetType()));
return (TResult)handler.Handle(query);
}
}
异常
An exception of type 'Autofac.Core.Registration.ComponentNotRegisteredException' occurred in Autofac.dll but was not handled in user code Additional information: The requested service 'PromocjeWsieciowkach.Messaging.Core.ICommandHandler`1[[PromocjeWsieciowkach.Messaging.Core.ICommand, PromocjeWsieciowkach.Messaging.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
堆栈跟踪
at Autofac.ResolutionExtensions.ResolveService(IComponentContext context, Service service, IEnumerable
1 parameters) at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable
1 parameters) at PromocjeWsieciowkach.Messaging.Factories.CqrsHandlerFactory.GetCommandHandler[TCommand](TCommand command) in C:\Users\Daniel\Desktop\PromocjeWsieciowkach\src\PromocjeWsieciowkach.Messaging\Factories\CqrsHandlersFactory.cs:line 17 at PromocjeWsieciowkach.Messaging.Bus.CqrsBus.ExecuteCommand(ICommand command) in C:\Users\Daniel\Desktop\PromocjeWsieciowkach\src\PromocjeWsieciowkach.Messaging\Bus\CqrsBus.cs:line 17 at PromocjeWsieciowkach.Controllers.PostController.Index() in C:\Users\Daniel\Desktop\PromocjeWsieciowkach\src\PromocjeWsieciowkach\Controllers\PostController.cs:line 20 at lambda_method(Closure , Object , Object[] ) at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__28.MoveNext()
所以我做错了什么?
您的代码和异常消息清楚地表明了问题。总之,您的异常消息说明:
The requested service 'ICommandHandler<ICommand>' has not been registered.
换句话说,您请求的是 ICommandHandler<ICommand>
而不是 ICommandHandler<TestCommand>
。这可以在这里看到:
public void ExecuteCommand(ICommand command)
{
var handler = cqrsHandlerFactory.GetCommandHandler(command);
// ...
}
C# 编译器将类型推断应用于 GetCommandHandler<T>
调用。所以下面的代码才是真正的调用:
var handler = cqrsHandlerFactory.GetCommandHandler<ICommand>(command);
您应该将 ICrqsBus.ExecuteCommand
方法更改为以下内容:
public void ExecuteCommand<TCommand>(TCommand command)
{
// You can merge the factory and your CqrsBus. Splitting them is useless.
var handler = cqrsHandlerFactory.GetCommandHandler<TCommand>();
// You don't need then null check; Autofac never returns null.
handler.Handle(command);
}
如果你不能使 ExecuteCommand
方法通用(例如,因为你不知道编译时的命令类型),你应该使用反射 API 构建通用类型作为如下:
public class CqrsBus : ICqrsBus
{
private readonly IComponentContext context;
public CqrsBus(IComponentContext context)
{
this.context = context;
}
public void ExecuteCommand(ICommand command)
{
Type handlerType = typeof(ICommandHandler<>).MakeGenericType(command.GetType());
dynamic handler = this.context.Resolve(handlerType);
void handler.Execute((dynamic)command);
}
}
同样值得注意的是,如果您使用 nopcommerce 并添加服务,如果您忘记在依赖注册器中添加服务,则会生成相同的错误。
builder.RegisterType<YourService>().As<IYourService>().InstancePerLifetimeScope();
我自己刚遇到这个,下面引用:
The requested service 'ICommandHandler' has not been registered."
让我了解依赖注册商。
谢谢史蒂文