? 首先,現(xiàn)有的三層項(xiàng)目的結(jié)構(gòu)
其中? Repository
public interface IPersonRepository
{
string Eat();
}
public class PersonRepository : IPersonRepository
{
public string Eat()
{
return "吃飯";
}
}
?Service
public interface IPersonService
{
string Eat();
}
public class PersonService : IPersonService
{
private IPersonRepository _personRespository;
//通過(guò)構(gòu)造函數(shù)注入 repository
public PersonService(IPersonRepository personRespository)
{
_personRespository = personRespository;
}
public string Eat()
{
return _personRespository.Eat();
}
}
?
一、安裝Autofac
? ? ? nuget上安裝Autofac
?
二、替換內(nèi)置的DI框架
將Startup.cs中的??ConfigureServices?
?返回類型改為??IServiceProvider,然后新起一個(gè)方法RegisterAutofac把創(chuàng)建容器的代碼放到其中,然后建一個(gè)?
?AutofacModuleRegister類繼承Autofac的Module,然后重寫(xiě)Module的Load方法 來(lái)存放新組件的注入代碼,避免Startup.cs文件代碼過(guò)多混亂。
? ??
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
return RegisterAutofac(services);//注冊(cè)Autofac
}
private IServiceProvider RegisterAutofac(IServiceCollection services)
{
//實(shí)例化Autofac容器
var builder = new ContainerBuilder();
//將Services中的服務(wù)填充到Autofac中
builder.Populate(services);
//新模塊組件注冊(cè)
builder.RegisterModule<AutofacModuleRegister>();
//創(chuàng)建容器
var Container = builder.Build();
//第三方IOC接管 core內(nèi)置DI容器
return new AutofacServiceProvider(Container);
}
public class AutofacModuleRegister:Autofac.Module
{
//重寫(xiě)Autofac管道Load方法,在這里注冊(cè)注入
protected override void Load(ContainerBuilder builder)
{
//注冊(cè)Service中的對(duì)象,Service中的類要以Service結(jié)尾,否則注冊(cè)失敗
builder.RegisterAssemblyTypes(GetAssemblyByName("WXL.Service")).Where(a => a.Name.EndsWith("Service")).AsImplementedInterfaces();
//注冊(cè)Repository中的對(duì)象,Repository中的類要以Repository結(jié)尾,否則注冊(cè)失敗
builder.RegisterAssemblyTypes(GetAssemblyByName("WXL.Repository")).Where(a => a.Name.EndsWith("Repository")).AsImplementedInterfaces();
}
/// <summary>
/// 根據(jù)程序集名稱獲取程序集
/// </summary>
/// <param name="AssemblyName">程序集名稱</param>
/// <returns></returns>
public static Assembly GetAssemblyByName(String AssemblyName)
{
return Assembly.Load(AssemblyName);
}
}
?
此時(shí)Autofac基本使用已經(jīng)配好了。
三、測(cè)試效果
? ? ? ? 修改HomeController?實(shí)現(xiàn)注入Service
public class HomeController : Controller
{
private IPersonService _personService;
//通過(guò)構(gòu)造函數(shù)注入Service
public HomeController(IPersonService personService)
{
_personService = personService;
}
public IActionResult Index()
{
ViewBag.eat = _personService.Eat();
return View();
}
}
頁(yè)面結(jié)果:
四、一個(gè)接口多個(gè)實(shí)現(xiàn)的情況
比喻我現(xiàn)在在Service?中建三個(gè)類,IPayService, WxPayService,AliPayService,其中WxPayService,AliPayService都實(shí)現(xiàn)接口IPayService。
public interface IPayService
{
string Pay();
}
public class AliPayService : IPayService
{
public string Pay()
{
return "支付寶支付";
}
}
public class WxPayService : IPayService
{
public string Pay()
{
return "微信支付";
}
}
? 先試一下結(jié)果,修改HomeController
public class HomeController : Controller
{
private IPersonService _personService;
private IPayService _payService;
//通過(guò)構(gòu)造函數(shù)注入Service
public HomeController(IPersonService personService,IPayService payService)
{
_personService = personService;
_payService = payService;
}
public IActionResult Index()
{
ViewBag.eat = _personService.Eat();
ViewBag.pay = _payService.Pay();
return View();
}
}
? View
@{
ViewData["Title"] = "Home Page";
}
@ViewBag.eat <br />
@ViewBag.pay
輸出頁(yè)面:
? ? 最后得到的是微信支付,因?yàn)閮蓚€(gè)對(duì)象實(shí)現(xiàn)一個(gè)接口的時(shí)候,注冊(cè)時(shí)后面注冊(cè)的會(huì)覆蓋前面注冊(cè)的。如果我想得到支付寶支付要怎么做呢?
我們可以用另外一種注冊(cè)方式RegisterType,修改注冊(cè)方式AutofacModuleRegister.cs。
?
public class AutofacModuleRegister:Autofac.Module
{
//重寫(xiě)Autofac管道Load方法,在這里注冊(cè)注入
protected override void Load(ContainerBuilder builder)
{
//注冊(cè)Service中的對(duì)象,Service中的類要以Service結(jié)尾,否則注冊(cè)失敗
builder.RegisterAssemblyTypes(GetAssemblyByName("WXL.Service")).Where(a => a.Name.EndsWith("Service")).AsImplementedInterfaces();
//注冊(cè)Repository中的對(duì)象,Repository中的類要以Repository結(jié)尾,否則注冊(cè)失敗
builder.RegisterAssemblyTypes(GetAssemblyByName("WXL.Repository")).Where(a => a.Name.EndsWith("Repository")).AsImplementedInterfaces();
//單獨(dú)注冊(cè)
builder.RegisterType<WxPayService>().Named<IPayService>(typeof(WxPayService).Name);
builder.RegisterType<AliPayService>().Named<IPayService>(typeof(AliPayService).Name);
}
/// <summary>
/// 根據(jù)程序集名稱獲取程序集
/// </summary>
/// <param name="AssemblyName">程序集名稱</param>
/// <returns></returns>
public static Assembly GetAssemblyByName(String AssemblyName)
{
return Assembly.Load(AssemblyName);
}
}
?
用Named區(qū)分兩個(gè)組件的不同,后面的typeof(WxPayService).Name?是任意字符串,這里直接用這個(gè)類名作標(biāo)識(shí),方便取出來(lái)時(shí)也是用這個(gè)名字,不易忘記。
然后就是取出對(duì)應(yīng)的組件了,取的時(shí)候用Autofac的 上下文(IComponentContext)?,修改HomeController
public class HomeController : Controller
{
private IPersonService _personService;
private IPayService _wxPayService;
private IPayService _aliPayService;
private IComponentContext _componentContext;//Autofac上下文
//通過(guò)構(gòu)造函數(shù)注入Service
public HomeController(IPersonService personService, IComponentContext componentContext)
{
_personService = personService;
_componentContext = componentContext;
//解釋組件
_wxPayService = _componentContext.ResolveNamed<IPayService>(typeof(WxPayService).Name);
_aliPayService =_componentContext.ResolveNamed<IPayService>(typeof(AliPayService).Name);
}
public IActionResult Index()
{
ViewBag.eat = _personService.Eat();
ViewBag.wxPay = _wxPayService.Pay();
ViewBag.aliPay = _aliPayService.Pay();
return View();
}
}
?Index View:
@{
ViewData["Title"] = "Home Page";
}
@ViewBag.eat <br />
@ViewBag.wxPay <br />
@ViewBag.aliPay
結(jié)果:
?
完成。
?
?
本文摘自 :https://blog.51cto.com/u