当前位置: 首页 > 编程语言 > C#

使用Simple Injector在C#中实现域事件处理程序模式分享

时间:2023-04-10 15:27:17 C#

C#学习教程:使用简单注入器在C#中实现域事件处理程序模式我已经将我的代码缩减为一个可以作为控制台应用程序运行的文件,并且我已经排除了SimpleInjector代码以使这个问题变得清晰。我的IEvent的问题是每个事件可能有多个事件处理程序,并且可能引发多个事件,但我想限制我的Dispatcher只处理实现IEvent接口的事件,所以我把这个限制放在我的高级Dispatch方法中。这导致了如何从SimpleInjector获取实例的问题,因为每次调用Dispatch方法时TEvent都是IEvent类型(如我所料),但我需要获取传入的事件类型,以便我可以获取关联的SimpleInjector的处理程序。希望我的代码能够更好地解释这个:interfaceIEvent{}interfaceIEventHandlerwhereT:IEvent{voidHandle(T@event);}classStandardEvent:IEvent{}classAnotherEvent:IEvent{}classStandardEventHandler:IEventHandler{publicvoidHandle(StandardEvent@event){Console.WriteLine("StandardEventhandled");}}classAnotherEventHandler:IEventHandler{publicvoidHandle(AnotherEvent@event){Console.WriteLine("AnotherEventhandled");}}这是我的调度员:staticclassDispatcher{//我需要在这里获取@event的类型,这样我就可以从//IoC容器(SimpleInjector)中获取注册的实例,但是TEvent是IEvent类型(如预期的)。//我在这里需要做的是从简单注入器为每个//事件类型获取注册实例,即Container.GetAllInstances()//和Container.GetAllInstances()publicstaticvoidDispatch(TEvent@event)其中TEvent:IEvent{}}classPlainOldObject{publicICollectionEvents=newList{newStandardEvent(),newAnotherEvent()};}classStandAlone{staticvoidMain(string[]args){varpoco=newPlainOldObject();foreach(var@eventinpoco.Events){Dispatcher.Dispatch(@event);我在Dispatch方法中评论了我的问题有谁知道如何解决这个问题?此致,加里您需要的解决方案在某种程度上取决于Dispatcher的消费者调用事件的方式。如果消费者在编译时总是知道事件的确切类型,则可以使用上面显示的通用Dispatch(TEvent)方法。这样的话,Dispatcher的实现就会很简单。另一方面,消费者可能并不总是知道确切的类型,但只是使用IEvent接口,Dispatch(TEvent)的泛型类型参数变得无用,您最好定义一个Dispatch(IEvent)方法。这使得实现更加复杂,因为你需要使用反射来解决这个问题。另请注意,最好引入IEventDispatcher抽象。不要在代码中调用静态类。甚至UdiDahan(很久以前最初描述过这个静态类的人)现在也认为它是一种反模式。相反,将IEventDispatcher抽象注入到需要事件分派的类中。如果所有消费者都使用编译时已知的事件类型,您的实现将如下所示:publicinterfaceIEventDispatcher{voidDispatcher(TEvent@event)whereTEvent:IEvent;}privatesealedclassDispatcher:IEventDispatcher{privatereadonlyContainercontainer;publicDispatcher(Containercontainer){this.container=container;}publicvoidDispatch(TEvent@event)whereTEvent:IEvent{if(@event==null)thrownewArgumentNullException("event");变种处理程序=这个。容器.GetAllInstances>();foreach(处理程序中的var处理程序){handler.Handle(@event);另一方面,如果事件类型未知,则可以使用以下代码:publicinterfaceIEventDispatcher{voidDispatch(IEvent@event);}privatesealedclassDispatcher:IEventDispatcher{privatereadonlyContainer容器;publicDispatcher(Containercontainer){this.container=container;}publicvoidDispatch(IEvent@event){if(@event==null)thrownewArgumentNullException("event");输入handlerType=typeof(IEventHandler).MakeGenericType(@event.GetType());VArhandlers=this.container.GetAllInstances(handlerType);foreach(处理程序中的动态处理程序){handler.Handle((dynamic)@event);注意,使用dynamic关键字有一些不明显的优点,例如,当动态调用处理程序的Handle方法时,句柄抛出的任何异常都会直接冒泡。另一方面,当使用MethodInfo.Invoke时,异常将被包装在一个新的异常中。这使得捕获和调试更加困难。您的事件处理程序可以按如下方式注册:container.RegisterCollection(typeof(IEventHandler),listOfAssembliesToSearch);要使用SimpleInjector并动态注入域事件,您可以执行以下操作:然后创建一个事件publicclassPolicyAddressChangedEvent:IDomainEvent{publicAddressNewAddress{get;}publicAddressOriginalAddress{get;}publicPolicyAddressChangedEvent(AddressoldBillingAddress,AddressnewbillingAddress){OriginalAddress=oldBillingAddress;NewAddress=newbillingAddress;}}然后为该事件创建一个处理程序publicclassPolicyAddressChangeHandler:IDomainEventHandler{privatereadonlyILoggingService_loggingService;publicPolicyAddressChangeHandler(ILoggingServiceloggingService){_loggingService=loggingService;}publicvoidHandle(PolicyAddressChangedEventdomainEvent){_loggingService.Info("新政策地址记录",newDictionary{{"新地址",domainEvent.NewAddress}},"FrameworkSample");//这可能是事件中心、队列或signalR消息、更新数据仓库、发送电子邮件,甚至更新其他域上下文}}现在在使用简单注入器创建IDomainEventDistpatcher时注入正确的注入,你A可以使用工厂注入器,这是获取所有类型并能够动态查找它们的关键。通过这样做,我们将Func注入到DomainEventDispatcher中。_container.RegisterSingleton(()=>{returnnewDomainEventDispatcher(type=>_container.GetInstance(type));});现在我们在DomainEventDispatcherpublicclassDomainEventDispatcher:IDomainEventDispatcher{privatereadonlyFunc_handlerLookup;_handlerLookup=handlerLookup;}publicvoidDispatch(IDomainEventdomainEvent){TypehandlerType=typeof(IDomainEventHandler).MakeGenericType(domainEvent.GetType());varhandler=GetHandler(handlerType);if(handler!=null){handler.Handle((dynamic)domainEvent);}}privatedynamicGetHandler(TypefilterType){try{objecthandler=_handlerLookup.Invoke(filterType);返回处理程序;}赶上(异常){返回空;现在,这将获取IDomainEvent并创建正确的类型,并根据提供的Func进行查找。这更好,因为现在我们不强制依赖类了解我们正在使用的DI实现。与上面史蒂文的回答非常相似(有一些小改动),只是想也会提供一个完整的例子。以上就是C#学习教程:使用SimpleInjector在C#中实现领域事件处理器模式的全部内容分享。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文来自网络收藏,不代表立场,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处: