Implementing Domain Event Handler pattern in C# with Simple Injector

后端 未结 3 877
南方客
南方客 2021-02-02 04:20

I am trying to implement the Domain Event pattern in C# using Simple Injector.

I have simplified my code to be in one file that can be ran as a console app and have excl

3条回答
  •  盖世英雄少女心
    2021-02-02 05:19

    To use SimpleInjector and get the domain event injected dynamically you could do the following:

    In the SI registrations

    _container.Register(typeof(IDomainEventHandler<>), new[] { typeof(IDomainEventHandler<>).Assembly});
    

    Then create a event

     public class PolicyAddressChangedEvent : IDomainEvent
        {
            public Address NewAddress { get;  }
            public Address OriginalAddress { get;  }
    
            public PolicyAddressChangedEvent(Address oldBillingAddress, Address newbillingAddress)
            {
                OriginalAddress = oldBillingAddress;
                NewAddress = newbillingAddress;
            }
        }
    

    Then create a handler for the event

    public class PolicyAddressChangeHandler : IDomainEventHandler
        {
            private readonly ILoggingService _loggingService;
    
            public PolicyAddressChangeHandler(ILoggingService loggingService)
            {
                _loggingService = loggingService;
            }
    
            public void Handle(PolicyAddressChangedEvent domainEvent)
            {
                _loggingService.Info("New policy address recorded", new Dictionary { { "new address", domainEvent.NewAddress } }, "FrameworkSample");
                //this could be event hub, queues, or signalR messages, updating a data warehouse, sending emails, or even updating other domain contexts
            }
        }
    

    Now to inject the correct one when you create your IDomainEventDistpatcher with simple injector you use a factory injector. This is the key to getting all the types and being able to look them up dynamically. By doing it like this we are injecting a Func into the DomainEventDispatcher.

     _container.RegisterSingleton(() =>
                                                            {
                                                                return new DomainEventDispatcher(type => _container.GetInstance(type));
                                                            });
    

    Now in the DomainEventDispatcher we have

    public class DomainEventDispatcher : IDomainEventDispatcher
        {
            private readonly Func _handlerLookup;
    
            public DomainEventDispatcher(Func handlerLookup)
            {
                _handlerLookup = handlerLookup;
            }
    
            public void Dispatch(IDomainEvent domainEvent)
            {
                Type handlerType = typeof(IDomainEventHandler<>).MakeGenericType(domainEvent.GetType());
                var handler = GetHandler(handlerType);
                if (handler != null)
                {
                    handler.Handle((dynamic)domainEvent);
                }
            }
    
            private dynamic GetHandler(Type filterType)
            {
                try
                {
                    object handler = _handlerLookup.Invoke(filterType);
                    return handler;
                }
                catch (Exception)
                {
                    return null;
                }
            }
        }
    

    This now takes the IDomainEvent and creates the correct type and looks that up based on the Func provided.

    This is better because now we dont force the dependency on the class to know about the DI implementation we are using. Very similar to Steven's anwser above (with some small tweeks), just thought would also provide a complete example too.

提交回复
热议问题