ioc container - Domain Events Implementation Using StructureMap Error -
i trying grasp fundamentals of raising/handling domain event in solution. using visual studio 2017, .net core 1.1, c#, structuremap 4.5.1.
the failure in code came light in unit test failed when checking if domain event being raised correctly.
my startup.cs class includes following code:
public iserviceprovider configureservices(iservicecollection services) { services.addsingleton(_config); services.addautomapper(); services.addmvc() .addcontrollersasservices(); return configureioc(services); } public iserviceprovider configureioc(iservicecollection services) { var container = new container(); container.configure(config => { config.scan(scan => { scan.assemblycontainingtype(typeof(startup)); scan.assembly("shared"); scan.assembly("taskscheduling"); scan.assembly("taskscheduling_tests"); scan.withdefaultconventions(); scan.connectimplementationstotypesclosing(typeof(ihandle<>)); }); //populate container using service collection config.populate(services); }); return container.getinstance<iserviceprovider>(); } where possible have been following udi dahan's approach domain events - salvation
my domainevents class implements following interface:
using system; namespace shared.interfaces { public interface idomainevent { datetime datetimeeventoccurred { get; } } } the domainevents class follows:
using system; using system.collections.generic; using shared.interfaces; using structuremap; namespace shared { /// <summary> /// http://udidahan.com/2009/06/14/domain-events-salvation/ /// http://msdn.microsoft.com/en-gb/magazine/ee236415.aspx#id0400046 /// /// class registers domain events , makes sure called. /// </summary> public static class domainevents { [threadstatic] private static list<delegate> actions; public static icontainer container { get; set; } // registers callback given domain event. public static void register<t>(action<t> callback) t : idomainevent { if (actions == null) { actions = new list<delegate>(); } actions.add(callback); } // clears callbacks passed register on current thread. public static void clearcallbacks() { actions = null; } // raises given domain event. public static void raise<t>(t args) t : idomainevent { foreach (var handler in container.getallinstances<ihandle<t>>()) { handler.handle(args); } if (actions != null) { foreach (var action in actions) { if (action action<t>) { ((action<t>)action)(args); } } } } } } i have task class when updated raises taskupdatedevent. taskupdatedevent class follows:
using shared.interfaces; using system; namespace taskscheduling.model.events { public class taskupdatedevent : idomainevent { /// <summary> /// when creating taskupdatedevent have pass in task object. /// </summary> /// <param name="task"></param> public taskupdatedevent(scheduleaggregate.task task) : this() { taskupdated = task; } public taskupdatedevent() { this.id = guid.newguid(); datetimeeventoccurred = datetime.now; // idomainevent interface requirement. } public guid id { get; private set; } public datetime datetimeeventoccurred { get; private set; } public scheduleaggregate.task taskupdated { get; private set; } } } and event raised following lines in task class:
var taskupdatedevent = new taskupdatedevent(this); domainevents.raise(taskupdatedevent); i have 1 unit test, far, check if event being raised. unit test follows:
using system; using nunit.framework; using shared; using taskscheduling.model.scheduleaggregate; using taskscheduling.model.events; namespace taskscheduling_tests { [testfixture] public class taskupdatedeventshould { private task testtask; private readonly guid testscheduleid = guid.newguid(); private const int testlocationid = 567; private const int testdeviceid = 123; private const int testtasktypeid = 1; private readonly datetime teststarttime = new datetime(2014, 7, 1, 9, 0, 0); private readonly datetime testendtime = new datetime(2014, 7, 1, 9, 30, 0); private readonly datetimerange newtasktimerange = new datetimerange(new datetime(2014, 6, 9, 10, 0, 0), timespan.fromhours(1)); private const string testtitle = "unit test title"; [setup] public void setup() { domainevents.clearcallbacks(); testtask = task.create( testscheduleid, testlocationid, testdeviceid, testtasktypeid, teststarttime, testendtime, testtitle ); } [test] public void entityconstructor_isnot_null() { assert.isnotnull(testtask); } [test] public void raisetaskupdatedevent() { // arrange guid updatedappointmentid = guid.empty; domainevents.register<taskupdatedevent>(aue => { // defines happens when event raised/ // 'updatedappointmentid' changed being zeros testtask's id value. updatedappointmentid = testtask.id; }); // act testtask.updatetime(newtasktimerange); // assert assert.areequal(testtask.id, updatedappointmentid); } } } the failure appears occur in domainevent class when raise method called. debugging shows event raised , arguments set, container null foreach loop cannot check handlers.
i cannot figure out why container null i'm sure must missing obvious. suggestions welcome.
Comments
Post a Comment