概述
ASP.NET Core 支持依賴關係注入 (DI) 軟件設計模式,這是一種在類及其依賴關係之間實現控制反轉 (IoC) 的技術。
默認服務容器是 Microsoft.Extensions.DependencyInjection 。
內置的服務容器一般能滿足簡單的框架和部分消費者應用的需求。 建議使用內置容器,除非你需要的特定功能不受內置容器支持,例如:
屬性注入
基於名稱的注入
子容器
自定義生存期管理
對遲緩初始化的 Func<T> 支持
基於約定的註冊
而大部分情況下,實際項目中往往是比較複雜的,所以可以使用其他第三方IOC容器,如Autofac;
Autofac
Autofac 是.Net世界中最常用的依賴注入框架之一. 相比.Net Core標準的依賴注入庫, 它提供了更多高級特性, 比如動態代理和屬性注入.
優點:
它是C#語言聯繫很緊密,也就是說C#裏的很多編程方式都可以爲Autofac使用,例如可以用Lambda表達式註冊組件
較低的學習曲線,學習它非常的簡單,只要你理解了IoC和DI的概念以及在何時需要使用它們
XML配置支持
自動裝配
具體使用
1、項目中引用
<PackageReference Include="Autofac" Version="4.9.1" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.3.1" />
2、準備好類、接口
using System.Collections.Generic;
namespace AspNetCoreExample.Services
{
public interface IValuesService
{
IEnumerable<string> FindAll();
string Find(int id);
}
}
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
namespace AspNetCoreExample.Services
{
public class ValuesService : IValuesService
{
private readonly ILogger<ValuesService> _logger;
public ValuesService(ILogger<ValuesService> logger)
{
_logger = logger;
}
public IEnumerable<string> FindAll()
{
_logger.LogDebug("{method} called", nameof(FindAll));
return new[] { "value1", "value2" };
}
public string Find(int id)
{
_logger.LogDebug("{method} called with {id}", nameof(Find), id);
return $"value{id}";
}
}
}
3、替換掉內置的Ioc
using System;
using System.Linq;
using Autofac.Extensions.DependencyInjection;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
namespace AspNetCoreExample
{
public class Program
{
public static void Main(string[] args)
{
// The ConfigureServices call here allows for
// ConfigureContainer to be supported in Startup with
// a strongly-typed ContainerBuilder. If you don't
// have the call to AddAutofac here, you won't get
// ConfigureContainer support. This also automatically
// calls Populate to put services you register during
// ConfigureServices into Autofac.
var host = WebHost.CreateDefaultBuilder(args)
.ConfigureServices(services => services.AddAutofac())
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}
using System;
using System.Linq;
using Autofac;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace AspNetCoreExample
{
// ASP.NET Core docs for Autofac are here:
// https://autofac.readthedocs.io/en/latest/integration/aspnetcore.html
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
this.Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; private set; }
public void Configure(IApplicationBuilder app)
{
app.UseMvc();
}
public void ConfigureContainer(ContainerBuilder builder)
{
// Add any Autofac modules or registrations.
// This is called AFTER ConfigureServices so things you
// register here OVERRIDE things registered in ConfigureServices.
//
// You must have the call to AddAutofac in the Program.Main
// method or this won't be called.
builder.RegisterModule(new AutofacModule());
}
public void ConfigureServices(IServiceCollection services)
{
// Use extensions from libraries to register services in the
// collection. These will be automatically added to the
// Autofac container.
//
// Note if you have this method return an IServiceProvider
// then ConfigureContainer will not be called.
services.AddMvc();
}
}
}
4、注入我們準備好的測試類、接口
using Autofac;
using AspNetCoreExample.Services;
using Microsoft.Extensions.Logging;
namespace AspNetCoreExample
{
public class AutofacModule : Module
{
protected override void Load(ContainerBuilder builder)
{
// The generic ILogger<TCategoryName> service was added to the ServiceCollection by ASP.NET Core.
// It was then registered with Autofac using the Populate method. All of this starts
// with the services.AddAutofac() that happens in Program and registers Autofac
// as the service provider.
builder.Register(c => new ValuesService(c.Resolve<ILogger<ValuesService>>()))
.As<IValuesService>()
.InstancePerLifetimeScope();
}
}
}
5、小試牛刀,用起來
using System.Collections.Generic;
using AspNetCoreExample.Services;
using Microsoft.AspNetCore.Mvc;
namespace AspNetCoreExample.Controllers
{
/// <summary>
/// Simple REST API controller that shows Autofac injecting dependencies.
/// </summary>
/// <seealso cref="Microsoft.AspNetCore.Mvc.Controller" />
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly IValuesService _valuesService;
public ValuesController(IValuesService valuesService)
{
this._valuesService = valuesService;
}
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return this._valuesService.FindAll();
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
return this._valuesService.Find(id);
}
}
}