小编典典

为什么我需要 IoC 容器而不是直接的 DI 代码?

all

我使用依赖注入(DI)
已经有一段时间了,在构造函数、属性或方法中注入。我从来没有觉得需要使用控制反转(IoC)
容器。然而,我读得越多,我就越觉得来自社区的使用 IoC 容器的压力越大。

我使用过 .NET
容器,例如StructureMapNInjectUnityFunq。我仍然看不到
IoC 容器将如何使我的代码受益/改进。

我也害怕在工作中开始使用容器,因为我的许多同事会看到他们不理解的代码。他们中的许多人可能不愿意学习新技术。

请说服我我需要使用 IoC 容器。当我与工作中的开发人员同事交谈时,我将使用这些论点。


阅读 119

收藏
2022-03-06

共1个答案

小编典典

哇,不敢相信乔尔会喜欢这个:

var svc = new ShippingService(new ProductLocator(), 
   new PricingService(), new InventoryService(), 
   new TrackingRepository(new ConfigProvider()), 
   new Logger(new EmailLogger(new ConfigProvider())));

对此:

var svc = IoC.Resolve<IShippingService>();

许多人没有意识到您的依赖链可以嵌套,并且手动连接它们很快就会变得笨拙。即使有工厂,重复代码也是不值得的。

IoC 容器可能很复杂,是的。但是对于这个简单的案例,我已经证明它非常简单。


好吧,让我们进一步证明这一点。假设您有一些要绑定到智能 UI 的实体或模型对象。这个智能 UI(我们称之为 Shindows Morms)希望您实现
INotifyPropertyChanged,以便它可以进行更改跟踪并相应地更新 UI。

“好吧,这听起来不那么难”,所以你开始写作。

你从这个开始:

public class Customer
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime CustomerSince { get; set; }
    public string Status { get; set; }
}

..最终得到 这个

public class UglyCustomer : INotifyPropertyChanged
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            string oldValue = _firstName;
            _firstName = value;
            if(oldValue != value)
                OnPropertyChanged("FirstName");
        }
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            string oldValue = _lastName;
            _lastName = value;
            if(oldValue != value)
                OnPropertyChanged("LastName");
        }
    }

    private DateTime _customerSince;
    public DateTime CustomerSince
    {
        get { return _customerSince; }
        set
        {
            DateTime oldValue = _customerSince;
            _customerSince = value;
            if(oldValue != value)
                OnPropertyChanged("CustomerSince");
        }
    }

    private string _status;
    public string Status
    {
        get { return _status; }
        set
        {
            string oldValue = _status;
            _status = value;
            if(oldValue != value)
                OnPropertyChanged("Status");
        }
    }

    protected virtual void OnPropertyChanged(string property)
    {
        var propertyChanged = PropertyChanged;

        if(propertyChanged != null)
            propertyChanged(this, new PropertyChangedEventArgs(property));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

那是令人作呕的管道代码,我坚持认为,如果你手动编写这样的代码, 你就是在从你的客户那里偷东西 。有更好、更智能的工作方式。

听说过这个词,更聪明地工作,而不是更努力地工作吗?

想象一下,你团队中的某个聪明人走过来说:“这是一个更简单的方法”

如果您将您的属性虚拟化(冷静下来,这没什么大不了的),那么我们可以自动 编织 该属性行为。(这叫做AOP,不过不用管名字,专注于它会为你做什么)

根据您使用的 IoC 工具,您可以执行如下所示的操作:

var bindingFriendlyInstance = IoC.Resolve<Customer>(new NotifyPropertyChangedWrapper());

噗! 现在,所有手动 INotifyPropertyChanged BS 都会在相关对象的每个虚拟属性设置器上为您自动生成。

这是魔法吗? 是的 !如果您可以相信此代码可以完成其工作这一事实,那么您可以安全地跳过所有包装 mumbo-jumbo
的属性。你有业务问题需要解决。

使用 IoC 工具执行 AOP 的其他一些有趣用途:

  • 声明式和嵌套数据库事务
  • 声明式和嵌套的工作单元
  • 日志记录
  • 前置/后置条件(按合同设计)
2022-03-06