依赖注入基础知识

几乎任何控制器都需要一些外部依赖项才能工作。这是一种配置依赖项对象(或其工厂)并将其传递给控制器​​的方法。这样做有助于维持关注点分离 ,保持代码清晰可测。

比如说,我们有一个接口及其实现,需要在其构造函数中使用 config 中的一些值:

public interface ISomeDependency
{
    async Task<IEnumerable<string>> GetItemsAsync(string key);
}

public class SomeDependency : ISomeDependency
{
    public SomeDependency(string connectionString)
    {
        ...
    }
    ...
}

它用在某些控制器类中:

public class SomeController : Controller
{
    private reanonly ISomeDependency dependency;

    public SomeController(ISomeDependency dependency)
    {
        ...
        this.dependency = dependency;
    }

    ...

    public async Task<IEnumerable<string>> Get(string key) =>
        await dependency.GetItemsAsync(key);
}

可以在 Startup.ConfigureServices 方法中调用 services.AddTransient 的控制器构造函数中注入此依赖项:

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder().
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
        ...
        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddTransient(serviceProvider =>
            new MyDependency(Configuration["Data:ConnectionString"]));
    }

    ...
}

这里 Data:ConnectionStringappsettings.json 文件中设置的路径:

{
  ...
  },
  "Data": {
    "ConnectionString": "some connection string"
  }
}

终身管理

为了管理注入对象的生命周期,与 AddTransient 一起存在另外两个选项:AddSingletonAddScoped。最后一个意味着对象的生命周期限定为 HTTP 请求。