ASP.NET Core 2.0使用Autofac实现IOC依赖注入竟然能如此的优雅简便
初识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”类内将注入代码类注册到项目中就可正常使用了。
声明
本文为作者原创,转载请备注出处与保留原文地址,谢谢。如文章能给您带来帮助,请点下推荐或关注,感谢您的支持!
上一篇: 弹出遮罩层后,如何禁止底层页面的滚动
下一篇: 写博一年收获的不仅仅是写作技能