Questions tagged «dependency-injection»

依赖注入是一种设计模式,其中通过构造函数,方法或字段(属性)设置组件的依赖关系(对象的实例,属性)。它是更一般的依赖项反转的一种特殊形式。

4
如何在依赖注入中处理“循环依赖”
标题说“ Circular Dependency”,但这不是正确的措辞,因为对我来说,设计似乎很牢固。 但是,请考虑以下情形,其中蓝色部分由外部合作伙伴提供,橙色是我自己的实现。还假设有多个ConcreteMain,但我要使用一个特定的。(实际上,每个类都有更多的依赖关系,但是我在这里尝试简化它) 我想通过Depency Injection(Unity)实例化所有这些,但是我显然可以StackOverflowException在以下代码上找到,因为Runner试图实例化ConcreteMain,而ConcreteMain需要一个Runner。 IUnityContainer ioc = new UnityContainer(); ioc.RegisterType<IMain, ConcreteMain>() .RegisterType<IMainCallback, Runner>(); var runner = ioc.Resolve<Runner>(); 我该如何避免呢?有什么方法可以构造它,以便可以与DI一起使用?我现在正在执行的方案是手动设置所有内容,但这ConcreteMain在实例化它的类中具有硬性依赖。这就是我要避免的事情(在配置中使用Unity注册)。 下面的所有源代码(非常简化的示例!); public class Program { public static void Main(string[] args) { IUnityContainer ioc = new UnityContainer(); ioc.RegisterType<IMain, ConcreteMain>() .RegisterType<IMainCallback, Runner>(); var runner = ioc.Resolve<Runner>(); Console.WriteLine("invoking runner..."); runner.DoSomethingAwesome(); Console.ReadLine(); } } …

3
大量构建一种实现。DI无望吗?使用服务定位器?
假设我们有1001个客户端,它们直接构造其依赖关系,而不接受注入。根据我们的老板,重构1001不是一个选择。实际上,甚至不允许我们访问其源代码,而只能访问类文件。 我们应该做的是“现代化”这1001个客户所经历的系统。我们可以重构自己喜欢的一切。依赖关系是该系统的一部分。还有一些依赖关系我们应该更改为具有新的实现。 我们想要做的是能够配置依赖关系的不同实现,以满足众多客户的需求。可悲的是,DI似乎不是一个选择,因为客户端不接受构造函数或setter的注入。 选项: 1)重构客户端使用的服务的实现,以使其执行客户端现在需要的功能。砰,我们完成了。不灵活。不复杂。 2)重构实现,以便将其工作委托给它通过工厂获取的另一个依赖项。现在,我们可以通过重构工厂来控制它们都使用哪种实现。 3)重构实现,以便将其工作委托给它通过服务定位器获取的另一个依赖项。现在,我们可以通过配置服务定位器来控制它们都使用哪种实现,该服务定位器可能只是hashmap对象的字符串,并且需要进行一些强制转换。 4)我什至没有想到的东西。 目标: 在不增加毫无意义的复杂性的情况下,将因设计欠佳的旧客户端代码拖到将来而导致的设计损失最小化。 客户不应该了解或控制其依赖项的实现,但是他们坚持使用来构建它们new。我们无法控制,new但可以控制他们正在构建的类。 我的问题: 我没有考虑什么? Doc Brown的问题 您是否真的需要在不同的实现之间进行配置?出于什么目的? 敏捷。很多未知数。管理层希望变革的潜力。只失去对外界的依赖。还测试。 您是否需要运行时机制或只是编译时机制来在不同的实现之间进行切换?为什么? 编译时间机制可能就足够了。除测试外。 您需要在实现之间切换哪种粒度?一次全部?每个模块(每个模块包含一组类)?每堂课? 在1001中,任何一次都只能运行一次。一次更改所有客户端使用的内容可能很好。但是,对依赖项的单独控制可能很重要。 谁需要控制开关?只有您/您的开发人员团队?管理员?每个客户自己吗?还是客户的代码的维护开发人员?那么,机械师需要多么容易/稳健/万无一失? 开发测试。管理员随着外部硬件依赖性的变化而变化。它需要易于测试和配置。 我们的目标是证明该系统可以快速重建和现代化。 实施开关的实际用例? 一种是,在硬件解决方案准备就绪之前,一些数据将由软件提供。

5
遵循TDD是否不可避免地导致DI?
我学会了同时进行测试驱动开发(TDD),依赖注入(DI)和控制反转(IoC)。当我使用TDD编写代码时,我总是最终在类的构造函数中使用DI。我想知道这是因为我学会了如何进行TDD,还是这是TDD的自然副作用。 所以我的问题是:遵循TDD原理和编写不依赖外部服务的单元测试是否不可避免地导致DI?

3
穷人的依赖注入是将可测试性引入旧版应用程序的好方法吗?
在过去的一年中,我使用依赖注入和IOC容器创建了一个新系统。这教会了我很多关于DI的知识! 但是,即使在学习了概念和正确的模式之后,我仍然认为将代码解耦并将IOC容器引入旧版应用程序是一个挑战。该应用程序足够大,以至于真正的实现将是压倒性的。即使理解了价值并准予了时间。谁有时间抽出这样的东西? 当然,目标是将单元测试引入业务逻辑! 与防止测试的数据库调用交织在一起的业务逻辑。 我已经阅读了这些文章,并且了解了这篇Los Techies文章中描述的穷人依赖注入的危险。我了解它并没有真正分离任何东西。 我知道它可能涉及很多系统范围的重构,因为实现需要新的依赖项。我不会考虑在任何大小的新项目中使用它。 问题:可以使用穷人的DI 将可测试性引入旧版应用程序并开始滚动吗? 另外,使用穷人的DI作为真正依赖注入的基层方法是否是教育该原理的需求和收益的有价值的方法? 您是否可以重构具有数据库调用依赖关系的方法,并将该调用抽象到接口后面?简单地拥有这种抽象将使该方法可测试,因为可以通过构造函数重载传递模拟实现。 将来,一旦获得支持者的支持,就可以对该项目进行更新以实现IOC容器,并且构造函数将在那里使用抽象。

3
MVVM和服务模式
我正在使用MVVM模式构建WPF应用程序。现在,我的视图模型调用服务层以检索模型(与视图模型无关)并将其转换为视图模型。我正在使用构造函数注入将所需的服务传递给viewmodel。 它易于测试,并且适用于几乎没有依赖关系的viewmodel,但是当我尝试为复杂模型创建viewModels时,我就有了一个构造函数,其中注入了很多服务(一个用于检索每个依赖关系和所有可用值的列表)绑定到itemsSource)。我想知道如何处理这样的多种服务,并且仍然拥有一个可以轻松进行单元测试的视图模型。 我在考虑一些解决方案: 创建一个包含所有可用服务作为接口的服务单例(IServices)。示例:Services.Current.XXXService.Retrieve(),Services.Current.YYYService.Retrieve()。这样,我就没有一个包含大量服务参数的庞大构造函数。 为viewModel使用的服务创建外观,并将此对象传递到我的viewmodel的ctor中。但是,然后,我必须为我的每个复合视图模型创建一个外观,这可能会有点多... 您认为实现这种架构的“正确”方法是什么?

4
通过这种方式,我编写此代码是可测试的,但是我缺少它吗?
我有一个名为的界面IContext。出于此目的,除了以下内容外,它的作用并不重要: T GetService<T>(); 该方法的作用是查看应用程序的当前DI容器,并尝试解决依赖关系。我认为还算标准。 在我的ASP.NET MVC应用程序中,我的构造函数如下所示。 protected MyControllerBase(IContext ctx) { TheContext = ctx; SomeService = ctx.GetService<ISomeService>(); AnotherService = ctx.GetService<IAnotherService>(); } 因此,我不是在为每个服务的构造函数中添加多个参数(因为这对于扩展应用程序的开发人员来说确实很烦人和耗时),而是使用此方法来获取服务。 现在,感觉不对。但是,我目前在脑海中证明它的方式是这样- 我可以嘲笑它。 我可以。模拟IContext测试控制器并不难。无论如何,我必须: public class MyMockContext : IContext { public T GetService<T>() { if (typeof(T) == typeof(ISomeService)) { // return another mock, or concrete etc etc } // etc …

6
质疑依赖关系注入框架的论点之一:为什么创建对象图很难?
像Google Guice这样的依赖注入框架为其使用(来源)提供了以下动机: 要构造一个对象,首先要建立它的依赖关系。但是要构建每个依赖项,您需要其依赖项,依此类推。因此,在构建对象时,确实需要构建对象图。 手工构建对象图是劳动密集型(...),并且使测试变得困难。 但是我不赞成这种观点:即使没有依赖注入框架,我也可以编写易于实例化且易于测试的类。例如,Guice动机页面中的示例可以用以下方式重写: class BillingService { private final CreditCardProcessor processor; private final TransactionLog transactionLog; // constructor for tests, taking all collaborators as parameters BillingService(CreditCardProcessor processor, TransactionLog transactionLog) { this.processor = processor; this.transactionLog = transactionLog; } // constructor for production, calling the (productive) constructors of the collaborators public BillingService() …

3
依赖注入框架会带来依赖风险吗?
我一直在重构现有系统以使用依赖项注入,并且该工作进展顺利。 一段时间后,我注意到大量内部库变得依赖于我使用的DI框架。结果,整个项目现在都依赖于此第三方框架。 在使所有依赖项依赖于共享库来解耦所有依赖项时,我感到讽刺。 我的第一个反应是围绕依赖关系框架创建包装器库。因此,如果需要,我可以替换此框架。在估计了所涉及的工作之后,我意识到最终的API将类似于现有框架,因此使替换它变得更加困难。所以我放弃了这个主意。 我担心的是,我正在使用的DI框架已过时或需要替换。 使用DI时是否存在减少项目和DI框架之间耦合的开发模式?

3
依赖注入:在什么时候可以创建一个新对象?
我正在重构PHP应用程序,并且我试图做的是尽可能多的依赖项注入(DI)。 我觉得我已经很好地了解了它的工作原理,而且我当然可以看到我的课程变得更加精简和强大。 我进行重构,以便可以在类中注入依赖关系而不是创建一个新对象,但是在某些时候,我将不得不创建一些对象,即使用dreaded new关键字。 我现在遇到的问题是我实际上可以在什么时候创建新对象?看起来我将结束于顶级课程,创建大量新对象,因为没有其他可去之处。这感觉不对。 我读过一些使用工厂类创建所有对象的博客,然后将工厂注入其他类中。然后,您可以调用工厂方法,然后工厂为您创建新对象。 我担心的是,现在我的工厂班将new全部免费!我猜这是工厂类的方法,这可能是可以的,但是使用工厂模式和DI时是否要遵守一些规则,还是我在这里偏离了常规?

4
手动进行依赖注入是否可以更好地替代组成和多态性?
首先,我是入门级程序员;实际上,我正在整个夏季完成AS学位,并完成了最终的顶峰项目。在我的新工作中,当我没有什么项目要做(他们正在等待团队中有更多新员工的到来)时,我在等待的过程中会得到一些可供阅读和学习的书籍-一些教科书,其他与其说是“代码完成”,不如说是。看完这些书之后,我转向互联网学习尽可能多的知识,并开始学习SOLID和DI(我们谈论了Liskov的替代原理,但没有其他SOLID想法)。因此,据我所知,我坐下来做得更好,并且开始编写一些代码以手工使用DI(开发计算机上没有DI框架)。 正如我所做的那样,我发现它感觉很熟悉……而且似乎很像我过去使用多态抽象类的组合所做的工作。我在这里想念大图吗?关于DI(至少是手工),还有其他一些东西吗?我了解在某些DI框架的代码中不包含配置的可能性,这些优点在无需重新编译的情况下就具有很大的好处,但是在手工操作时,我不确定它是否与上述内容有所不同...对此有一些了解将非常有帮助!

8
暴露异步功能的接口是泄漏抽象吗?
我正在阅读《依赖注入原理,实践和模式》一书,并了解了泄漏抽象的概念,该概念在本书中有很好的描述。 这些天来,我正在使用依赖注入重构C#代码库,以便使用异步调用而不是阻塞调用。这样做时,我正在考虑一些接口,这些接口在我的代码库中表示抽象,并且需要重新设计以便可以使用异步调用。 例如,考虑以下接口,它代表应用程序用户的存储库: public interface IUserRepository { Task<IEnumerable<User>> GetAllAsync(); } 根据书中的定义,泄漏抽象是设计时考虑到特定实现的抽象,因此某些实现详细说明了抽象本身的“泄漏”。 我的问题如下:我们可以考虑以异步方式设计的接口(例如IUserRepository)作为泄漏抽象的示例吗? 当然,并非所有可能的实现都与异步有关:只有进程外实现(例如SQL实现)才需要同步,但是内存中存储库不需要异步(实际上实现接口的内存中版本可能更多)如果接口公开异步方法很困难,例如,您可能必须在方法实现中返回类似Task.CompletedTask或Task.FromResult(users)之类的东西。 您如何看待?

4
表示依赖注入相反的技术术语?
这更多是术语(技术写作),而不是纯粹的技术问题。我正在尝试围绕我们的应用程序中扩展依赖项注入编写一个重构建议(并将其分配给我自己)。虽然我们确实使用Spring来自动装配Bean,但是仍然存在使用实例化Bean的实例,这些实例MyClass obj = new MyClass(...)可以完全注入。我想使我的建议使用优雅的命名法,并用适当的术语指代DI的设计模式。 “紧密耦合”是否足以作为DI的反义词?

2
依赖注入样式之间的实际区别是什么?
我是依赖注入的新手,我对应在应用程序中使用哪种样式有一些疑问。我刚刚阅读了Martin Fowler 的《控制容器的反转》和《依赖注入》模式,但是我无法获得构造函数,setter和接口注入之间的实际区别。 在我看来,一个使用另一个的原因仅是代码清理和/或清晰的问题。有什么区别?相对于其他方法,使用它们有什么优点或缺点,还是我刚才所说的? 在我看来,构造函数注入是最直观的,而接口注入则是最少的。另一方面,setter注入是一个中间术语,但是,您是否应该能够更改最初注入的依赖对象的实例?这种注入方式是否可以确保需要依赖项的对象始终被注入?我相信不会,但是如果我错了,请纠正我。

2
n层实体框架解决方案的依赖注入
我当前正在设计一个使用实体框架5(.net 4)作为其数据访问策略的n层解决方案,但是我担心如何合并依赖项注入以使其可测试/灵活。 我当前的解决方案布局如下(我的解决方案称为Alcatraz): Alcatraz.WebUI:一个asp.net Webform项目(前端用户界面)引用项目Alcatraz.Business和Alcatraz.Data.Models。 Alcatraz.Business:一个类库项目,包含业务逻辑,引用项目Alcatraz.Data.Access,Alcatraz.Data.Models Alcatraz.Data.Access:一个类库项目,包含AlcatrazModel.edmx和AlcatrazEntitiesDbContext,引用项目Alcatraz.Data.Models。 Alcatraz.Data.Models:一个类库项目,包含Alcatraz模型的POCO,无引用。 我对这个解决方案如何工作的愿景是,Web-ui将实例化业务库中的存储库,该存储库将具有(通过构造函数)连接字符串(而不是AlcatrazEntities实例)的依赖项。Web用户界面会知道数据库连接字符串,但不知道它是一个实体框架连接字符串。 在业务项目中: public class InmateRepository : IInmateRepository { private string _connectionString; public InmateRepository(string connectionString) { if (connectionString == null) { throw new ArgumentNullException("connectionString"); } EntityConnectionStringBuilder connectionBuilder = new EntityConnectionStringBuilder(); connectionBuilder.Metadata = "res://*/AlcatrazModel.csdl|res://*/AlcatrazModel.ssdl|res://*/AlcatrazModel.msl"; connectionBuilder.Provider = "System.Data.SqlClient"; connectionBuilder.ProviderConnectionString = connectionString; _connectionString = connectionBuilder.ToString(); } …

3
IValidaableObject与单一责任
我喜欢MVC的可扩展性,它允许视图模型实现IValidatableObject,并添加自定义验证。 我尝试使我的控制器保持精简,使此代码成为唯一的验证逻辑: if (!ModelState.IsValid) return View(loginViewModel); 例如,登录视图模型实现IValidatableObject,通过构造函数注入获取ILoginValidator对象: public interface ILoginValidator { bool UserExists(string email); bool IsLoginValid(string userName, string password); } 似乎在视图模型中注入实例的Ninject并不是真正的惯例,甚至可能是反模式? 这是一个好方法吗?有更好的吗?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.