隐藏

.net core2.1 三层中使用Autofac代替原来Ioc

发布:2022/3/29 14:30:28作者:管理员 来源:本站 浏览次数:914

首先,现有的三层项目的结构


其中  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;

       //通过构造函数注入 repository

       public  PersonService(IPersonRepository personRespository)

       {

         _personRespository = personRespository;

       }

       public string Eat()

       {

           return  _personRespository.Eat();

       }

   }


复制代码



一、安装Autofac


     nuget上安装Autofac



二、替换内置的DI框架


将Startup.cs中的ConfigureServices返回类型改为IServiceProvider,然后新起一个方法RegisterAutofac把创建容器的代码放到其中,然后建一个AutofacModuleRegister类继承Autofac的Module,然后重写Module的Load方法 来存放新组件的注入代码,避免Startup.cs文件代码过多混乱。


   

复制代码


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);//注册Autofac

       }


复制代码

复制代码


private IServiceProvider RegisterAutofac(IServiceCollection services)

       {

           //实例化Autofac容器

           var builder = new ContainerBuilder();

           //将Services中的服务填充到Autofac中

           builder.Populate(services);

           //新模块组件注册    

           builder.RegisterModule<AutofacModuleRegister>();

           //创建容器

           var Container = builder.Build();

           //第三方IOC接管 core内置DI容器

           return new AutofacServiceProvider(Container);

       }


复制代码

复制代码


public class AutofacModuleRegister:Autofac.Module

   {

       //重写Autofac管道Load方法,在这里注册注入

       protected override void Load(ContainerBuilder builder)

       {

           //注册Service中的对象,Service中的类要以Service结尾,否则注册失败

           builder.RegisterAssemblyTypes(GetAssemblyByName("WXL.Service")).Where(a => a.Name.EndsWith("Service")).AsImplementedInterfaces();

           //注册Repository中的对象,Repository中的类要以Repository结尾,否则注册失败

           builder.RegisterAssemblyTypes(GetAssemblyByName("WXL.Repository")).Where(a => a.Name.EndsWith("Repository")).AsImplementedInterfaces();          

       }

       /// <summary>

       /// 根据程序集名称获取程序集

       /// </summary>

       /// <param name="AssemblyName">程序集名称</param>

       /// <returns></returns>

       public static Assembly GetAssemblyByName(String AssemblyName)

       {

           return Assembly.Load(AssemblyName);

       }

   }


复制代码




此时Autofac基本使用已经配好了。

三、测试效果


       修改HomeController 实现注入Service

复制代码


public class HomeController : Controller

   {

       private IPersonService _personService;

     

       //通过构造函数注入Service

       public HomeController(IPersonService personService)

       {

           _personService = personService;

       }

       public IActionResult Index()

       {

           ViewBag.eat = _personService.Eat();

           return View();

       }

}


复制代码


页面结果:


四、一个接口多个实现的情况


比喻我现在在Service 中建三个类,IPayService, WxPayService,AliPayService,其中WxPayService,AliPayService都实现接口IPayService。


public interface IPayService

   {

       string Pay();

   }


复制代码


public class AliPayService : IPayService

   {

       public string Pay()

       {

           return "支付宝支付";

       }

   }


复制代码

复制代码


public class WxPayService : IPayService

   {

       public string Pay()

       {

           return "微信支付";

       }

   }


复制代码


 先试一下结果,修改HomeController

复制代码


public class HomeController : Controller

   {

       private IPersonService _personService;

       private IPayService _payService;

     

       //通过构造函数注入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


输出页面:


   最后得到的是微信支付,因为两个对象实现一个接口的时候,注册时后面注册的会覆盖前面注册的。如果我想得到支付宝支付要怎么做呢?


我们可以用另外一种注册方式RegisterType,修改注册方式AutofacModuleRegister.cs。



复制代码


public class AutofacModuleRegister:Autofac.Module

   {

       //重写Autofac管道Load方法,在这里注册注入

       protected override void Load(ContainerBuilder builder)

       {

           //注册Service中的对象,Service中的类要以Service结尾,否则注册失败

           builder.RegisterAssemblyTypes(GetAssemblyByName("WXL.Service")).Where(a => a.Name.EndsWith("Service")).AsImplementedInterfaces();

           //注册Repository中的对象,Repository中的类要以Repository结尾,否则注册失败

           builder.RegisterAssemblyTypes(GetAssemblyByName("WXL.Repository")).Where(a => a.Name.EndsWith("Repository")).AsImplementedInterfaces();

           //单独注册

           builder.RegisterType<WxPayService>().Named<IPayService>(typeof(WxPayService).Name);

           builder.RegisterType<AliPayService>().Named<IPayService>(typeof(AliPayService).Name);

       }

       /// <summary>

       /// 根据程序集名称获取程序集

       /// </summary>

       /// <param name="AssemblyName">程序集名称</param>

       /// <returns></returns>

       public static Assembly GetAssemblyByName(String AssemblyName)

       {

           return Assembly.Load(AssemblyName);

       }

   }


复制代码




用Named区分两个组件的不同,后面的typeof(WxPayService).Name 是任意字符串,这里直接用这个类名作标识,方便取出来时也是用这个名字,不易忘记。


然后就是取出对应的组件了,取的时候用Autofac的 上下文(IComponentContext) ,修改HomeController

复制代码


public class HomeController : Controller

   {

       private IPersonService _personService;

       private IPayService _wxPayService;

       private IPayService _aliPayService;

       private IComponentContext _componentContext;//Autofac上下文

       //通过构造函数注入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


结果:




完成。