欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP.NET Core 2.0使用Autofac实现IOC依赖注入竟然能如此的优雅简便

程序员文章站 2022-06-18 15:54:14
初识ASP.NET Core的小伙伴一定会发现,其几乎所有的项目依赖都是通过依赖注入方式进行链式串通的。这是因为其使用了依赖注入 (DI) 的软件设计模式,代码的设计是遵循着“高内聚、低耦合”的原则,使得各个类与类之间的关系依赖于接口,这样做的目的是能更有利于项目代码的维护与扩展。 ......

初识asp.net core的小伙伴一定会发现,其几乎所有的项目依赖都是通过依赖注入方式进行链式串通的。这是因为其使用了依赖注入 (di) 的软件设计模式,代码的设计是遵循着“高内聚、低耦合”的原则,使得各个类与类之间的关系依赖于接口,这样做的目的是能更有利于项目代码的维护与扩展。

 

autofac

在进入主题之前咱们还是先来简单的认识下鼎鼎大名的“autofac”吧。那么何为autofac呢,通俗的讲就是一个开源的,且基于.net core、asp.net core、.net 4.5.1+等框架实现的控制反转(ioc)类库。通过autofac可以在.net core、asp.net core、.net 4.5.1+等项目上很容易的实现依赖注入,代码很容易就能达到“高内聚、低耦合”的原则。另外,现在autofac的中文资料也很多,需要详细了解的也可在网上自行查看。

autofac官方网站:

 

背景

在我们大部分的项目中都会将代码抽成多层,每层之间通过相互依赖串联工作。在这里,我们将asp.net core项目代码抽成三层结构,分别为输入输出层(mvc项目)、业务层(类库)、数据层(类库),每层的功能描述如下:

1、lezhima.web:接受来自客户端的请求,及服务端响应的出入口。由一个基于asp.net core的mvc项目组成。

2、lezhima.core:根据请求做出相应的业务判断,及调度上下游数据并计算,输出相应的业务结果给调用者。由一个基于.net core的类库组成。

3、lezhima.data:直接跟db进行通讯交互,实现对db的增、删、改、查等操作。由一个基于.net core的类库组成。

依赖关系:

基于上述中的三层代码结构,我们可以清晰的看出lezhima.web做为项目出入口,在其需要时会调用lezhima.core类库,并将业务交由lezhima.core库处理,而lezhima.core类库在其需要时会调用lezhima.data类库操作db。那么,它们之间的依懒关系应该是这样子的:

1、lezhima.web同时依赖于lezhima.core与lezhima.data类库。

2、lezhima.core依赖于lezhima.data类库。

 

实现代码

通过上面的介绍,我们清楚了三个分层之间的功能与依赖关系,那么接下来我们就分别来看看它们具体代码及使用autofac如何优雅的实现依赖注入吧。

1、首先在lezhima.web项目中通过nuget管理器引用:autofac、autofac.extensions.dependencyinjection两个类库。

2、我们先来看看lezhima.data层的代码,首先定义一个名为“irepository”接口,代码如下:

  1 using system;
  2 using system.collections.generic;
  3 using system.data;
  4 using system.linq;
  5 using system.linq.expressions;
  6 using system.text;
  7 using system.threading.tasks;
  8 
  9 namespace lezhima.data.interface
 10 {
 11     public interface irepository<t> where t : class
 12     {
 13         /// <summary>
 14         /// 从指定的表中获取符合条件的一条实体数据
 15         /// </summary>
 16         /// <param name="predicate"></param>
 17         /// <returns></returns>
 18         task<t> getasync(expression<func<t, bool>> predicate);
 19     }
 20 }

 

3、在lezhima.data层再增加一个名为“repository”类,实现“irepository”接口,代码如下:

  1 using system;
  2 using system.collections.generic;
  3 using system.linq;
  4 using system.text;
  5 using system.threading.tasks;
  6 using system.data;
  7 using system.linq.expressions;
  8 using microsoft.entityframeworkcore;
  9 using system.data.sqlclient;
 10 using lezhima.data.interface;
 11 
 12 namespace lezhima.data
 13 {
 14     /// <summary>
 15     /// 数据层
 16     /// 实现irepository接口
 17     /// </summary>
 18     /// <typeparam name="t"></typeparam>
 19     public class repository<t> : irepository<t> where t : class
 20     {
 21 
 22         /// <summary>
 23         /// 从指定的表中获取符合条件的一条实体数据
 24         /// </summary>
 25         /// <param name="predicate"></param>
 26         /// <returns></returns>
 27         public async task<t> getasync(expression<func<t, bool>> predicate)
 28         {
 29             using (var db = new lezhimacontext())
 30             {
 31                 if (predicate == null)
 32                     return null;
 33 
 34                 return await db.set<t>().where(predicate).firstordefaultasync<t>();
 35             }
 36         }
 37     }
 38 }
 39 

 

4、在lezhima.core层再定义一个名为“iusercore”接口,代码如下:

  1 using system;
  2 using system.collections.generic;
  3 using system.text;
  4 using system.threading.tasks;
  5 
  6 namespace lezhima.core.interface
  7 {
  8     public interface iusercore
  9     {
 10         /// <summary>
 11         /// 根据账号密码判断用户是否拥有合法登录权限
 12         /// </summary>
 13         /// <param name="email"></param>
 14         /// <returns>100成功,101账号错误,102密码错误,103参数不合法</returns>
 15         task<mobiresult> login(string email,string pwd);
 16     }
 17 }
 18 

 

5、在lezhima.core层再增加一个名为“usercore”类,实现“iusercore”接口,代码如下:

  1 using lezhima.core.interface;
  2 using lezhima.data.interface;
  3 using system;
  4 using system.collections.generic;
  5 using system.text;
  6 using system.threading.tasks;
  7 
  8 namespace lezhima.core
  9 {
 10     public class usercore : iusercore
 11     {
 12         //定义一个依赖属性
 13         private readonly irepository<eb_user> _repository;
 14 
 15         /// <summary>
 16         /// 通过构造涵数方式注入data层的repository实例
 17         /// </summary>
 18         /// <param name="repository"></param>
 19         public usercore(irepository<eb_user> repository)
 20         {
 21             _repository = repository;
 22         }
 23 
 24 
 25         /// <summary>
 26         /// 根据账号密码判断用户是否拥有合法登录权限
 27         /// </summary>
 28         /// <returns>100成功,101账号错误,102密码错误,103参数不合法</returns>
 29         public async task<mobiresult> login(string email, string pwd)
 30         {
 31             if (string.isnullorempty(email) || string.isnullorempty(pwd))
 32                 return new mobiresult(103);
 33 
 34             //到data层去取指定用户的数据
 35             var model= await _repository.getasync(p => p.email.equals(email)&&p.isdelete!=99);
 36             if(model ==null)
 37                 return new mobiresult(101);
 38 
 39             if(!model.pwd.equals(pwd))
 40                 return new mobiresult(102);
 41 
 42             return new mobiresult(100);
 43         }
 44 
 45     }
 46 }
 47 

 

6、在lezhima.web层增加一个名为“accountcontroller ”的控制器,代码如下:

  1 using system;
  2 using system.collections.generic;
  3 using system.linq;
  4 using system.security.claims;
  5 using system.threading.tasks;
  6 using lezhima.core.interface;
  7 using microsoft.aspnetcore.authentication;
  8 using microsoft.aspnetcore.authentication.cookies;
  9 using microsoft.aspnetcore.authorization;
 10 using microsoft.aspnetcore.http;
 11 using microsoft.aspnetcore.mvc;
 12 
 13 namespace lezhima.web.controllers
 14 {
 15     [authorize]
 16     [autovalidateantiforgerytoken]
 17     public class accountcontroller : controller
 18     {
 19 
 20         //定义一个依赖属性
 21         private readonly iusercore _usercore;
 22 
 23         /// <summary>
 24         /// 通过构造涵数方式注入core层的usercore实例
 25         /// </summary>
 26         /// <param name="__usercore"></param>
 27         public accountcontroller(iusercore __usercore)
 28         {
 29             _usercore = __usercore;
 30         }
 31 
 32 
 33         // get: account
 34         public actionresult index()
 35         {
 36             return view();
 37         }
 38 
 39 
 40 
 41 
 42         /// <summary>
 43         /// 实现客户端的登录操作
 44         /// </summary>
 45         /// <param name="loginrequest"></param>
 46         /// <returns></returns>
 47         [httppost]
 48         [allowanonymous]
 49         public async task<iactionresult> login(loginrequest loginrequest)
 50         {
 51             var result = await _usercore.login(loginrequest.email, loginrequest.pwd);
 52 
 53             if (result.code != 100)
 54             {
 55                 viewbag.resultmodel = result;
 56                 return view();
 57             }
 58 
 59             //向客户端写入用户的身份cookie
 60             var _user = new claimsprincipal(new claimsidentity(new claim[]
 61             {
 62                     new claim("userid", user_model.userid.tostring()),
 63             }, cookieauthenticationdefaults.authenticationscheme));
 64             await httpcontext.signinasync(cookieauthenticationdefaults.authenticationscheme, _user);
 65 
 66             if (string.isnullorwhitespace(loginrequest.returnurl))
 67             {
 68                 return redirecttoaction("index", "home");
 69             }
 70             return redirect(loginrequest.returnurl);
 71         }
 72 
 73     }
 74 }

 

7、在lezhima.web层增加一个名为“evolution”的类,用于继承autofac的module类,实现上述三层之间的依赖关系注入,代码如下:

  1 using autofac;
  2 using lezhima.core;
  3 using lezhima.data;
  4 using lezhima.data.interface;
  5 using system;
  6 
  7 namespace lezhima.web.injection
  8 {
  9     /// <summary>
 10     /// 重写依赖注入的业务
 11     /// </summary>
 12     public class evolution : module
 13     {
 14         protected override void load(containerbuilder builder)
 15         {
 16             //注入data层的repository类
 17             builder.registergeneric(typeof(repository<>)).as(typeof(irepository<>)).instanceperdependency();
 18             //批量注入core层的类
 19             builder.registerassemblytypes(typeof(eb_usercore).assembly)
 20                     .where(t => t.name.endswith("core"))
 21                     .asimplementedinterfaces();
 22         }
 23     }
 24 }
 25 

 

8、在lezhima.web层的“startup”类的“configureservices”方法内注入即可,代码如下:

  1 public iconfiguration configuration { get; }
  2 
  3 public iserviceprovider configureservices(iservicecollection services)
  4 {
  5 	services.addmvc();
  6 
  7 	//将evolution注册到项目中来,实现依赖注入
  8 	var builder = new containerbuilder();
  9 	builder.registermodule(new evolution());
 10 	builder.populate(services);
 11 	var container = builder.build();
 12 	return container.resolve<iserviceprovider>();
 13 }

  

总结

1、每层在调用时,通过在该类内声明一个接口类型的属性(变量),再通过autofac构造涵数注入方式实现依赖注入并获取到相应的类实例。

2、通过继承autofac的module类,并在load方法内重写自已项目的类关系来实现注入业务。

3、autofac注入有多种不同的生命周期类型,分别为instanceperlifetimescope、singleinstance、instanceperdependency等,各位在项目中按需选择即可。

4、最后再通过在asp.net core项目内的“startup”类内将注入代码类注册到项目中就可正常使用了。

 

声明

本文为作者原创,转载请备注出处与保留原文地址,谢谢。如文章能给您带来帮助,请点下推荐或关注,感谢您的支持!