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

使用依赖注入框架时的抽象工厂分享

时间:2023-04-10 10:54:13 C#

使用依赖注入框架时的抽象工厂我想知道在使用DI框架时如何正确使用抽象工厂,要确定工厂中的其中一个参数由DI框架处理的依赖项。我不确定是否让我的抽象工厂完全省略参数,然后使用我的DI容器连接它,或者是否应该将依赖项传递给对象。例如,我有一个使用Session.Factory来创建套接字的TcpServer。Session对象实际上在其构造函数中使用了一个Processor。我应该将处理程序传递给TcpServer,然后将其传递给Session.Factory还是让我的DI容器进行布线?如果我让DI容器进行连接,它看起来像这样:classSession:ISession{publicdelegateISessionFactory(stringname);...publicSession(stringname,Processorprocessor){...}}classTcpServer:ITcpServer{privatereadonlySession.Factory_sessionFactory;publicTcpServer(Session.FactorysessionFactory){this._sessionFactory=socketFactory;}...publicvoidOnConnectionReceived(){...varsession=_sessionFactory(ip.LocalEndPoint());...}}然后使用像Ninject这样的DI容器,我可以在配置容器时这样做:Bind().ToMethod(c=>{varprocessor=Kernel.Get();return(name)=>newSession(name,处理器);}).InSingletonScope();这种方法的主要问题是它假设创建Session.Factory的人都知道处理器。就我而言,由于我使用的是DI容器,这实际上非常方便,但拥有一个具有自己依赖项的工厂似乎很奇怪。我总是想象一个没有任何成员的工厂。如果我想依赖类会话:ISession{publicdelegateISessionFactory(stringname,Processorprocessor);...publicSession(stringname,Processorprocessor){...}}classTcpServer:ITcpServer{privatereadonlySession.Factory_sessionFactory;私有只读处理器_processor;publicTcpServer(Session.FactorysessionFactory,Processor处理器){this._processor=processor;}...publicvoidOnConnectionReceived(){...varsession=_sessionFactory(ip.LocalEndPoint(),_process);...}}第二种方法有两个问题:TcpServer实际上并不对处理程序执行任何操作。它只是传递它。看起来可怜的人的DI几乎在工作。在这段代码背后的真实程序中,Processor实际上有一个对TcpServer的引用。所以当使用这个方法时,我得到了一个循环引用。当我使用第一个场景将其分离时,这不是问题。你认为最好的方法是什么?我也乐于接受新想法。谢谢!许多容器以一种或另一种方式支持工厂,这是您应该采用的方式。例如,像这样定义一个ISessionFactory接口publicinterfaceISessionFactory{ISessionCreateSession(stringname);对于Ninject2.3,请参见https://github.com/ninject/ninject.extensions.factory并让Ninject实现Bind().AsFactory();对于2.2自己实现publicclassSessionFactory:ISessionFactory{privateIKernelkernel;publicSessionFactory(IKernelkernel){this.kernel=kernel;}publicISessionCreateSession(stringname){returnthis.kernel.Get(newConstructorArgument("name",name));我用于抽象工厂模式的模式与您的略有不同。我在通用单例上使用类似setter注入的东西,但在更直观的界面中包装可配置的委托“属性”。我不想单独注册每个实现,所以我更愿意使用一些可以在应用程序启动时测试的约定。我不确定用于自动调整自定义约定的Ninject语法,但逻辑将归结为扫描相关程序集以查找具有类型为AbstractFactory的静态只读字段的引用类型T,然后在静态成员上调用Configure(Func)与反思。下面是一个通用抽象工厂单例的例子,以及它是如何在Session上声明的。publicclassSession{publicstaticreadonlyAbstractFactoryFactory=AbstractFactory.GetInstance();}publicsealedclassAbstractFactorywhereT:class{staticAbstractFactory(){Bolt=newobject();}privatestaticreadonlyobjectBolt;私有静态抽象工厂实例;publicstaticAbstractFactoryGetInstance(){if(Instance==null){lock(Bolt){if(Instance==null)Instance=newAbstractFactory();}}返回实例;}privateAbstractFactory(){}privateFuncm_FactoryMethod;publicvoidConfigure(FuncfactoryMethod){m_FactoryMethod=factoryMethod;}publicTCreate(){if(m_FactoryMethod==null){thrownewNotImplementedException();}返回m_FactoryMethod.Invoke();}}更新如果需要将参数传给工厂方法,则可以更改类,例如:publicsealedclassAbstractFactorywhereT:class{staticAbstractFactory(){Bolt=newobject();}privatestaticreadonlyobjectBolt;私有静态抽象工厂实例;公共静态抽象工厂GetInstance(){if(Instance==null){lock(Bolt){if(Instance==null)Instance=newAbstractFactory();}}返回实例;}privateAbstractFactory(){}privateFuncm_FactoryMethod;publicvoidConfigure(FuncfactoryMethod){m_FactoryMethod=factoryMethod;}publicTCreate(TDataContractdata){if(m_FactoryMethod==null){thrownewNotImplementedException();}返回m_FactoryMethod.Invoke(数据);}}您的SessionData,Session和TcpServer可能看起来像publicclassSessionData{publicDateTimeStart{get;放;}publicstringIpAddress{get;放;}}publicclassSession{publicstaticreadonlyAbstractFactoryFactory=AbstractFactory.GetInstance();私有只读字符串_ip;私人只读日期时间_start;公共会话(SessionData数据){_ip=data.IpAddress;_start=DateTime.Now;}公共事件EventHandlerRequestAdded;}publicclassRequestReceivedEventArgs:EventArgs{publicSessionRequestRequest{get;放;}}公共类TcpServer:ITcp服务器{私有只读处理器_processor;公共TcpServer(处理器处理器){this._processor=processor;}publicvoidOnConnectionReceived(){varsessionData=newSessionData{IpAddress=ip.LocalEndPoint(),Start=DateTime.Now};varsession=Session.Factory.Create(sessionData);//...做其他事情}publicvoidServeResponse(SessionRequestrequest){_processor.Process(request);在配置DI容器的时候,可以设置工厂,例如:以上是C#学习教程:使用依赖注入框架时抽象工厂分享的所有内容,如果对大家有用还需要了解更多关于C#学习教程,希望大家多多关注——Session.Factory.Configure(sessionData=>{//不是在Session中注入处理器,而是配置事件让TcpServer处理数据。//(毕竟,服务器为请求提供服务比会话执行处理更合乎逻辑。会话倾向于存储数据//和状态,而不是调用进程session.RequestAdded+=(sender,e)=>{Kernel.Get.ServeResponse(e.Request);};});本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如有转载请注明出处: