c# - Autofac Registration technique for this specific issue -


i have class:

public class autofaceventcontainer : ieventcontainer     {         private readonly icomponentcontext _context;          public autofaceventcontainer(icomponentcontext context)         {             _context = context;         }          public ienumerable<idomaineventhandler<t>> handlers<t>(t domainevent)                                                t : idomainevent         {             return _context.resolve<ienumerable<idomaineventhandler<t>>>();         }     } 

the ieventcontainer this:

public interface ieventcontainer     {          ienumerable<idomaineventhandler<t>> handlers<t>(t domainevent)             t : idomainevent;     } 

now ieventcontainer used in class domainevents this:

public static class domainevents     {          ....................................         ....................................          public static ieventcontainer container;             public static void raise<t>(t domainevent) t : idomainevent         {             if (container != null)                 foreach (var handler in container.handlers(domainevent))                     handler.handle(domainevent);              // registered actions, typically used unit tests.             if (_actions != null)                 foreach (var action in _actions)                     if (action action<t>)                         ((action<t>)action)(domainevent);         }       } 

my aim have domainevents.container registered handlers resolved.

 public class somemodule : module    {     protected override void load(containerbuilder builder)         {             base.load(builder);              //wrong way in autofac             //because following line ninject-like             domainevents.container = new autofaccontainer(componentcontext);             //what correct way register achieve above intent?           }     } 

what way in autofac?

you going have memory leak if resolve out of root scope. (see this post overview of lifetime scopes in autofac.) better way this:

interface ieventraiser {     void raise<tevent>(tevent @event) tevent : idomainevent; }  class autofaceventraiser : ieventraiser {     private readonly ilifetimescope context;      public autofaceeventraiser(ilifetimescope context)     {         this.context = context;     }      public void raise<tevent>(tevent @event) tevent : idomainevent     {         using(var scope = context.beginlifetimescope("eventraiser"))         {             foreach(var handler in scope.resolve<ienumerable<idomaineventhandler<tevent>>>())             {                 handler.handle(@event);             }         } // scope disposed - no memory leak     } }   // then, in composition root:  icontainer thecontainer = buildtheautofaccontainer(); domainevents.eventraiser = new autofaceventraiser(thecontainer); 

this simple answer, there 1 more caveat should aware of...

the question whether want use static ieventraiser. di purists say, "no - should inject instance of ieventraiser every class needs one", others have argued static event raiser ok.

be sure aware of how autofac's lifetime scopes work before make decsion, because affect component sharing. example, someclass has instance of somedependency , raises someevent. let assume somedependency instanceperlifetimescope.

  • if someclass gets ieventraiser injected, handlers invoked on same lifetime scope, , injected same instance of somedependency.
  • if someclass uses static ieventraiser, handlers invoked on different lifetime scope, , injected different instance of somedependency.

you can see why matters if imagine somedependency db transaction.


Comments

Popular posts from this blog

php - regexp cyrillic filename not matches -

c# - OpenXML hanging while writing elements -

sql - Select Query has unexpected multiple records (MS Access) -