.NET Core 2,DI,配置文件

时间:2018-09-10 13:26:34

标签: asp.net-core dependency-injection .net-core asp.net-core-mvc asp.net-core-webapi

我正在研究.NET Core 2,但我不喜欢如何管理DI ...在网络上,我读到以下内容:

  1. 创建类似IService的界面

  2. 为IService创建实现

  3. 将它在.NET Core容器的范围内添加到解决依赖关系的Startup.Configuration方法中。

  4. 最后,我可以将其用于自定义控制器的构造函数中。

在.NET classic中,我使用了专用的XML配置文件来管理依赖关系:是否可以使用配置文件(JSON或XML相同)来执行与Startup.Configuration方法相同的操作?

...否则有人可以向我解释为什么将服务配置为Startup.Configuration是更好的方法吗?

非常感谢...

1 个答案:

答案 0 :(得分:4)

首先,要回答您的问题“我可以使用配置文件”,答案是“是”。您稍后为什么不回答,但是现在,这是一个穷人版本,您可以通过添加到appsettings.json文件中来实现此目的。请注意,该代码不是最佳代码,但旨在向您展示如何可以实现该解决方案。

让我们从一些用于保存数据的类开始:

public class ServicesConfiguration
{
    public IEnumerable<ServiceItem> Singleton { get; set; }
    public IEnumerable<ServiceItem> Transient { get; set; }
}

public class ServiceItem
{
    public string Service { get; set; }
    public string Implementation { get; set; }
}

现在在您的JSON文件中添加一个部分,您甚至可能希望将此文件保留在主配置外部,但这是实现细节,我将留给您:

{
    //snip main config....

    "Services" : {
        "Singleton": [
            { 
                "Service": "YourNamespace.IFoo1, YourNamespace", 
                "Implementation": "YourNamespace.Foo1, YourNamespace" 
            },   
            {
                "Service": "YourNamespace.IFoo2, YourNamespace", 
                "Implementation": "YourNamespace.Foo2, YourNamespace" 
            }  
        ],
        "Transient": [
            {
                "Service": "YourNamespace.IBar1, YourNamespace",
                "Implementation": "YourNamespace.Bar1, YourNamespace"
            }    
        ]
    }
}

现在是一种扩展方法来配置所有功能:

public static IServiceCollection AddFromConfigurationFile(this IServiceCollection services, 
    IConfigurationSection configuration)
{
    var servicesConfiguration = configuration.Get<ServicesConfiguration>();

    foreach(var service in servicesConfiguration.Singleton)
    {
        services.AddSingleton(Type.GetType(service.Service), Type.GetType(service.Implementation));
    }

    foreach(var service in servicesConfiguration.Transient)
    {
        services.AddTransient(Type.GetType(service.Service), Type.GetType(service.Implementation));
    }

    //Other scopes here...

    return services;
}

像这样在ConifigureServices中调用它:

services.AddFromConfigurationFile(Configuration.GetSection("Services"));

那么,简单好吧?你为什么不这样做呢?一些想法浮出水面:

  1. 为什么要更改几乎所有DI实现的工作方式?如果没有破裂,为什么要修复它?仅仅因为您习惯于一种特定的方法,并不意味着它是一个好主意。
  2. 类型安全性:您丢失了在配置文件中指定的类型的编译时检查。
  3. 安全性:将其保存在配置文件中会使某人将实现更改为自己选择的类。

我确定还有更多,但这是您的应用!