Dependency injection 控制反转-XML还是Fluent API?

Dependency injection 控制反转-XML还是Fluent API?,dependency-injection,inversion-of-control,Dependency Injection,Inversion Of Control,我刚刚开始使用反转控制容器,在配置和注册组件时,我很难理解何时使用fluentapi或XML 当您应该选择其中一种而不是另一种时,是否有最佳实践?或者这仅仅是开发人员的偏好?将它们混合在一个简单的应用程序中会被认为是不好的做法吗 谢谢 我的最佳选择是两者的结合。XML,用于汇集大型功能单元,并可能在部署时对其进行配置;fluent用于在这些单元内设置各个组件。有关Autofac示例,请参见。其他容器通常具有类似的功能。代码中的容器配置(您称之为“fluent API”)更易于维护,因为代码是经过

我刚刚开始使用反转控制容器,在配置和注册组件时,我很难理解何时使用fluentapi或XML

当您应该选择其中一种而不是另一种时,是否有最佳实践?或者这仅仅是开发人员的偏好?将它们混合在一个简单的应用程序中会被认为是不好的做法吗


谢谢

我的最佳选择是两者的结合。XML,用于汇集大型功能单元,并可能在部署时对其进行配置;fluent用于在这些单元内设置各个组件。有关Autofac示例,请参见。其他容器通常具有类似的功能。

代码中的容器配置(您称之为“fluent API”)更易于维护,因为代码是经过编译的,因此编译器会为您发现许多错误。但是,如果要进行更改,则需要重新编译


XML中的容器配置正好相反:编译器无法帮助您查找错误,但您可以在不重新编译的情况下进行更改


如果您刚刚开始依赖注入,我会坚持使用代码中的配置来保持简单。

我注意到其他答案没有涉及Fluent配置给DI实现带来的一个非常重要的问题。这就是将具体实现硬连接到代码库,从而创建紧密耦合的依赖关系……讽刺的是,这正是IoC容器试图解决的问题。你会发现你自己用组件注册码污染了你所有的应用程序,这听起来不太好

为什么听起来不好?因为当您有一个分布式系统,其中有许多应用程序使用不同的组件时,您基本上有两个选项来注册您的组件:

1.在所有应用程序上添加DI代码。 像这样的

var builder = new ContainerBuilder();

builder.RegisterType<ConsoleLogger>().As<ILogger>();
builder.RegisterType<EmailNotificationDispatcher>().As<INotificationDispatcher>();
builder.RegisterType<DefaultMessageHandler>().As<IMessageHandler>();
//many more...
public sealed class ComponentFactory
{
    private static IContainer _container;

    public static void Init()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<ConsoleLogger>().As<ILogger>();
        builder.RegisterType<EmailNotificationDispatcher>().As<INotificationDispatcher>();
        builder.RegisterType<DefaultMessageHandler>().As<IMessageHandler>();
        //many more...
        _container = builder.Build();
    }

    public static T Resolve<T>()
    {
        return _container.Resolve<T>();
    }
}
var builder=newcontainerbuilder();
builder.RegisterType().As();
builder.RegisterType().As();
builder.RegisterType().As();
//还有很多。。。
当然,系统中的所有应用程序都需要这种具有不同组件的逻辑

优势 您使用Fluent配置是因为它很漂亮……仅此而已:)

缺点
  • 使用这种流畅的组件注册会污染所有应用程序,包括具体类型
  • 如果需要交换依赖项/组件,则需要重新编译应用程序
  • 如果您需要迁移到不同的IoC容器工具…相同
2.将DI代码包装在包装器组件中,使应用程序与IoC容器无关。 像这样的

var builder = new ContainerBuilder();

builder.RegisterType<ConsoleLogger>().As<ILogger>();
builder.RegisterType<EmailNotificationDispatcher>().As<INotificationDispatcher>();
builder.RegisterType<DefaultMessageHandler>().As<IMessageHandler>();
//many more...
public sealed class ComponentFactory
{
    private static IContainer _container;

    public static void Init()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<ConsoleLogger>().As<ILogger>();
        builder.RegisterType<EmailNotificationDispatcher>().As<INotificationDispatcher>();
        builder.RegisterType<DefaultMessageHandler>().As<IMessageHandler>();
        //many more...
        _container = builder.Build();
    }

    public static T Resolve<T>()
    {
        return _container.Resolve<T>();
    }
}
公共密封类组件工厂
{
专用静态IContainer\u容器;
公共静态void Init()
{
var builder=new ContainerBuilder();
builder.RegisterType().As();
builder.RegisterType().As();
builder.RegisterType().As();
//还有很多。。。
_container=builder.Build();
}
公共静态T解析()
{
返回_container.Resolve();
}
}
使用这种方法,您的应用程序根本无法有效地了解它们使用的是什么具体类。 如果需要交换组件,则不需要重新编译和重新部署所有应用程序。 此外,如果您需要迁移到不同的IoC容器,那么更改将在一个地方完成…包装器类。 这种方法的巨大缺点是,即使存在一个应用程序可能不需要的组件(或二进制程序集),您也必须将所有组件部署到所有应用程序的bin文件夹中。因此,您的轻量级应用程序将成为胖客户端

XML(或json)配置 使用xml配置,上述情况都不会发生

  • 您可以根据每个应用程序部署应用程序所需的内容
  • 您可以按每个应用程序注册应用程序所需的组件
  • 您的应用程序很轻,不知道它们使用的是什么具体实现。它们变得非常可伸缩
  • 还有更多,但希望你能理解
现在,我不是XML配置的倡导者,我讨厌它,我是一名编码员,更喜欢流畅的方式而不是XML(或json),但根据我的经验,XML/json配置被证明更具可伸缩性和可维护性

现在,开枪打我