2016-11-01 1 views
0

Je tente d'implémenter le modèle CQRS dans mon application. J'ai donc trouvé comment enregistrer tous les gestionnaires de commande de l'assemblage ici: Autofac resolve dependency in CQRS CommandDispatcherAutofac.Core.Registration.ComponentNotRegisteredException

Mais ça ne marche pas bien pour moi. Voici le code:

 containerBuilder.RegisterAssemblyTypes(assembly) 
      .AsClosedTypesOf(typeof(ICommandHandler<>)); 

     containerBuilder.RegisterAssemblyTypes(assembly) 
      .AsClosedTypesOf(typeof(IQueryHandler<,>)); 

Handlers usine

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>>(); 
    } 
} 

Bus

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); 
    } 
} 

Exception

Une exception de type 'Autofac.Core.Registration.ComponentNotRegisteredException' a eu lieu dans Autofac.dll mais n'a pas été manipulé dans le code utilisateur Informations supplémentaires: Le service demandé 'PromocjeWsieciowkach.Messaging.Core.ICommandHandler`1 [[PromocjeWsieciowkach.Messaging.Core.ICommand, PromocjeWsieciowkach.Messaging.Core, Version = 1.0.0.0, Culture = neutre, PublicKeyToken = null] ] 'n'a pas été enregistré. Pour éviter cette exception, enregistrez un composant pour fournir le service, recherchez l'enregistrement du service à l'aide de IsRegistered() ou utilisez la méthode ResolveOptional() pour résoudre une dépendance facultative.

Stacktrace

à Autofac.ResolutionExtensions.ResolveService (contexte IComponentContext, Service de service, IEnumerable 1 parameters) at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable 1 paramètres) à PromocjeWsieciowkach.Messaging.Factories.CqrsHandlerFactory.GetCommandHandler [TCommand] (commande TCommand) dans C: \ Utilisateurs \ Daniel \ Bureau \ PromocjeWsieciowkach \ src \ PromocjeWsieciowkach.Messaging \ Factories \ CqrsHandlersFactory.cs: ligne 17 à PromocjeWsieciowkach.Messaging.Bus.CqrsBus.ExecuteCommand (commande ICommand) dans C: \ Users \ Daniel \ Desktop \ PromocjeWsieciowkach \ src \ PromocjeWsieciowkach.Messaging \ Bus \ CqrsBus.cs: ligne 17 à PromocjeWsieciowkach.Controllers.PostController.Index() dans C: \ Users \ Daniel \ Desktop \ PromocjeWsieciowkach \ src \ PromocjeWsieciowkach \ Controllers \ PostController.cs: ligne 20 à lambda_method (fermeture, l'objet, l'objet []) à Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__28.MoveNext()

Alors qu'est-ce que je fais mal?

+0

Veuillez remplacer l'ima ges avec le code actuel et le texte du message d'exception (et toujours inclure des traces de pile). – Steven

+0

Veuillez inclure le code qui appelle cette méthode 'GetCommandHandler '. – Steven

+0

J'ai modifié mon message. – TjDillashaw

Répondre

5

Votre code et le message d'exception indiquent clairement le problème. En résumé, votre message d'exception explique que:

Le service demandé 'ICommandHandler < ICommand>' n'a pas été enregistré.

En d'autres termes, vous demandez un ICommandHandler<ICommand> au lieu d'un ICommandHandler<TestCommand>. Cela peut être vu ici:

public void ExecuteCommand(ICommand command) 
{ 
    var handler = cqrsHandlerFactory.GetCommandHandler(command); 
    // ... 
} 

Le compilateur C# inférence de type appliqué à l'appel GetCommandHandler<T>.Ainsi, le code suivant est l'appel réel:

var handler = cqrsHandlerFactory.GetCommandHandler<ICommand>(command); 

Vous devez changer la méthode ICrqsBus.ExecuteCommand à ce qui suit:

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); 
} 

Si vous ne pouvez pas faire la (par exemple générique méthode ExecuteCommand parce que vous ne faites pas connaître le type de commande au moment de la compilation), vous devez construire les types génériques en utilisant l'API de réflexion comme suit:

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); 
    } 
} 
+0

Merci pour l'explication claire. – TjDillashaw

+0

Si vous rencontrez ce problème avec nopcommerce vérifier ma réponse :) –

0

Il est également intéressant de noter que si vous En utilisant nopcommerce et en ajoutant un service, la même erreur est générée si vous oubliez d'ajouter votre service dans le registre de dépendance.

builder.RegisterType<YourService>().As<IYourService>().InstancePerLifetimeScope(); 

Juste suis tombé sur moi-même, et la citation suivante:.

Le service demandé 'ICommandHandler' n'a pas été enregistré »

m'a fait prendre conscience au sujet du bureau d'enregistrement de dépendance.

Merci Steven