用于小型.net项目的IoC/DI

本文关键字:IoC DI 项目 小型 net 用于 | 更新日期: 2023-09-27 18:08:41

对于大型项目来说,IoC/DI框架提供的关注点分离怎么估计都不过分,但是在小型项目中,这种技术有一席之地吗?

您能分享一些您在编写另一个小型/普通项目时发现的有用的IoC/DI框架的实际应用吗?

为了便于定义:

一个"小项目"包含100-1000行代码(大概来说,只是给一个想法),它需要1-3天的时间来编写代码,最终的应用程序在被丢弃或退役之前的生命周期是在最初发布后的1周- 5年(这是很难在小/一般/大项目之间划清界限的)。

谢谢。

用于小型.net项目的IoC/DI

对于一个小项目,我仍然倾向于使用依赖注入,但不使用框架。只需在入口点中制作所有依赖项。您仍然可以获得可测试性的所有好处,并且您可以稍后继续使用一个完全成熟的容器—但是在容器真正有用之前,您不需要担心设置容器的问题。

我在几个小项目中使用了这种方法,效果非常好。当然,这取决于你的依赖关系有多复杂——它们是否需要是工厂,是否有不同的作用域等等——但如果只是"我有这三样东西,它们都依赖于一个身份验证服务",那么这就相当简单了。

但是在一个小项目中有这样的技术吗?

即使在小项目中,您也应该使用IoC模式,以削弱层之间的耦合并使其单元可测试。总是使用抽象。是否使用DI框架并不重要。在小型项目中,您可以简单地手工完成依赖项的管道,实际上不需要对象容器来进行依赖项注入,但是当您重新考虑时,为什么不这样做呢?

取决于你认为在你的实现中什么是重要的。如果可测试性很重要,并且您倾向于遵循单一职责原则(在小型或大型项目中),那么您通常会得到比其他情况下更多的类。这可能导致像

这样的调用
var svc = new ShippingService(new ProductLocator(), 
                              new PricingService(), 
                              new InventoryService(), 
                              new TrackingRepository(new ConfigProvider()), 
                              new Logger(new EmailLogger(new ConfigProvider())));

如果你能忍受这一点,我个人也会这样做,在一个扔掉的应用程序中,那么无论如何你都不需要一个DI容器。做任何让你开心的事。欢呼。

编辑:

多年来,我发现TinyIoC是小型项目的一个很好的折衷方案。

我不会把IoC与项目规模联系在一起,而是:
  • 项目类数
  • 他们的依赖的复杂性
  • 预期维护和扩展量
  • 开发人员在扩展和维护期间的预期切换

特别是最后两个将使它更容易,如果你测试你的代码,你确实需要(它可以避免使用适当的工具,但是…)国际奥委会.

不要过度设计你的代码

因此,我建议初学者不要使用DI容器,但是在接口和双构造函数方面肯定要使用IoC,如:
public class Example : IExample // for others that might depend on it
{
    private IDependant service;
    // default constructor used in your application
    public Example() : this(new DependentService())
    {
        // does nothing else
    }
    // constructor for testing purposes
    public Example(IDependant service)
    {
        this.service = service;
    }
    // IExample implementation
}

简单的两级依赖关系无需使用DI容器即可轻松手动管理。而且用起来也更快。这将使您的代码易于测试,特别是如果您将bug作为测试用例提供,将自动避免未来的bug,请考虑这一点。

小项目趋向于成长

在商业环境中具有附加价值的小项目往往会被频繁地扩展,因为它推动了用户对事物如何进一步增强的想象。所以不要低估你的项目。它可能很快就会增长。

我写了很多类似规模的项目,每年30-40个。

我使用DI,但是用Resolve方法创建了自己的工厂类。

public T Resolve<T>()
    where T:class {
        if (typeof(T).IsAssignableFrom(typeof(Something)))
            return new Something(Resolve<ISomethingElse>()) as T;
        ...
}

我采取的一个快捷方式是将大多数成员设为虚的,而不是创建单独的接口

一般来说,为什么不为小型项目使用DI容器呢?你的代码库越简单,使用容器就越简单,我的建议是使用它为依赖项注册提供一个简单的流体接口,或者只是使用linq,那么你最终会得到一个非常小的占用空间,连接你的整个应用程序:

public void OnStartup(args){
    var container = new IoCContainerOfChoice();
    Types.FromThisAssembly()
        .ForEach(type => container.Register(type, type.DefaultInterface());
    container.Resolve<ShellView>();
}

对于许多小项目来说,这很简单。这个想法是用一行代码注册项目中所有类型的默认接口(我通常在"System. js"上写一个扩展方法)。键入"以选择一个命名接口、第一个接口或仅返回其本身)。注意:大多数现代IoC容器都有自己的Fluent接口来提供此功能,这只是一个示例。

嘿,看,你现在已经为未来的意外增长做好了准备,你可以为自己节省一堆"新东西",并解耦你的应用程序或大或小