2011-04-12 4 views
13

J'essaie d'introduire des événements de domaine dans un projet. Le concept est décrit dans le poste de Udi Dahan - http://www.udidahan.com/2009/06/14/domain-events-salvation/Utilisation d'Autofac avec les événements de domaine

est ici le domaine code événement

public interface IDomainEvent { } 

public interface IHandleDomainEvents<T> where T : IDomainEvent 
{ 
    void Handle(T args); 
} 

public interface IEventDispatcher 
{ 
    void Dispatch<TEvent>(TEvent eventToDispatch) where TEvent : IDomainEvent; 
} 

public static class DomainEvents 
{ 
    public static IEventDispatcher Dispatcher { get; set; } 

    public static void Raise<TEvent>(TEvent eventToRaise) where TEvent : IDomainEvent 
    { 
     Dispatcher.Dispatch(eventToRaise); 
    } 
} 

La partie la plus importante est la mise en œuvre IEventDispatcher qui découple l'événement de domaine de tout ce qui doit se produire lorsque l'événement est déclenché. L'astuce consiste à câbler ce couplage à travers un conteneur. Voici ma tentative

Code pour l'enregistrement de tous les gestionnaires d'événements de domaine ....

 var asm = Assembly.GetExecutingAssembly(); 
     var handlerType = typeof(IHandleDomainEvents<>); 

     builder.RegisterAssemblyTypes(asm) 
      .Where(t => handlerType.IsAssignableFrom(t) 
         && t.IsClass 
         && !t.IsAbstract) 
      .AsClosedTypesOf(handlerType) 
      .InstancePerLifetimeScope(); 

et résoudre tous les gestionnaires d'événements dans le répartiteur. Le problème est qu'aucun gestionnaire n'est résolu. Donc, je ne suis pas en train d'enregistrer correctement les gestionnaires d'événements ou de ne pas les résoudre. Comment vérifier que l'enregistrement fonctionne?

code Exemple d'un gestionnaire

public class SendWebQuestionToCSO : IHandleDomainEvents<JobNoteCreated> 
{ 
    private readonly IConfig _config; 

    public SendWebQuestionToCSO(IConfig config) 
    { 
     _config = config; 
    } 

    public void Handle(JobNoteCreated args) 
    { 
     var jobNote = args.JobNote; 
     using(var message = new MailMessage()) 
     { 
      var client = new SmtpClient {Host = _config.SmtpHostIp}; 
      message.From = new MailAddress(_config.WhenSendingEmailFromWebProcessUseThisAddress); 
      ...... etc 
     } 
    } 
} 

MISE À JOUR Après quelques essais et erreurs du EventDispatcher fonctionne ok! Si j'enregistre manuellement un gestionnaire, puis déclenche l'événement de domaine cela fonctionne. L'assemblage scan/registraion est mon problème. Le code d'enregistrement manuel ...

builder.RegisterType<SendWebQuestionToCSO >().As<IHandleDomainEvents<JobNoteCreated>>(); 

Alors, comment puis-je analyser tous les ensembles pour tous IHandleDomainEvents<> étant donné qu'ils ressemblent à ce

public class SendWebQuestionToCSO : IHandleDomainEvents<JobNoteCreated> 

Répondre

7

Comme Pierre l'a souligné, le problème de l'enregistrement était avec votre clause Where().

Lors de la numérisation des ensembles composants Filtres Autofac automatiquement en fonction des services que vous spécifiez, il serait tout aussi correct de simplement utiliser:

builder.RegisterAssemblyTypes(asm) 
    .AsClosedTypesOf(handlerType) 
    .InstancePerLifetimeScope(); 
+0

Parfait Nick! J'attends votre prochain cours avec impatience! – CRG

+0

Ah, oui, encore plus lisse. Robbed moi de 15 rep si! –

+0

Hé comme vous en avez besoin, ML;) vous avez néanmoins mon vote. –

1

Le problème dans votre code d'analyse d'assemblage est lorsque vous utilisez IsAssignableFrom. Le filtre demandera: "une instance de SendWebQuestionToCSO peut-elle être affectée à une variable de IHandleDomainEvents<>?" La réponse est évidemment "non" car vous ne pouvez jamais avoir une variable d'un type générique ouvert.

L'astuce consiste à inspecter les interfaces implémentées par chaque type et à vérifier si l'une d'entre elles ferme le type d'interface générique ouvert. Voici un scanner révisé:

var asm = Assembly.GetExecutingAssembly(); 
    var handlerType = typeof(IHandleDomainEvents<>); 

    builder.RegisterAssemblyTypes(asm) 
     .Where(t => t.GetInterfaces().Any(t => t.IsClosedTypeOf(handlerType))) 
     .AsImplementedInterfaces() 
     .InstancePerLifetimeScope(); 
+0

Salut Peter, dans quel espace de noms puis-je trouver 'IsClosingTypeOf' – CRG

+0

Voulez-vous dire IsClosedTypeOf? J'ai essayé, et ça n'a pas marché.Cependant, cela semblait très prometteur! Toutes les autres idées seraient très utiles Je suis en train de jouer avec cela depuis trop longtemps maintenant ... – CRG

+0

J'ai regardé la source sur le code.google.com hg/src/Source/Autofac/Util/ReflectionExtensions.cs et la méthode d'extension IsClosingTypeOf est très simple, j'ai donc copié le code résultant de - .Where (t => t.GetInterfaces(). Tout (i => i.IsGenericType && i.GetGenericTypeDefinition() == handlerType)). CELA MARCHE!!! La grande question est où la méthode d'extension est-elle allée dans la version 2.4.5.724 .Net4? – CRG

Questions connexes