博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET Core2使用Autofac实现IOC依赖注入竟然能如此的优雅简便
阅读量:5340 次
发布时间:2019-06-15

本文共 8532 字,大约阅读时间需要 28 分钟。

初识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官方网站:

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
where T : class 12 { 13 ///
14 /// 从指定的表中获取符合条件的一条实体数据 15 /// 16 ///
17 ///
18 Task
GetAsync(Expression
> 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     ///  15     /// 数据层 16     /// 实现IRepository接口 17     ///  18     /// 
19 public class Repository
: IRepository
where T : class 20 { 21 22 ///
23 /// 从指定的表中获取符合条件的一条实体数据 24 /// 25 ///
26 ///
27 public async Task
GetAsync(Expression
> predicate) 28 { 29 using (var db = new LezhimaContext()) 30 { 31 if (predicate == null) 32 return null; 33 34 return await db.Set
().Where(predicate).FirstOrDefaultAsync
(); 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         ///  11         /// 根据账号密码判断用户是否拥有合法登录权限 12         ///  13         ///  14         /// 
100成功,101账号错误,102密码错误,103参数不合法
15 Task
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
_Repository; 14 15 ///
16 /// 通过构造涵数方式注入Data层的Repository实例 17 /// 18 ///
19 public UserCore(IRepository
repository) 20 { 21 _Repository = repository; 22 } 23 24 25 ///
26 /// 根据账号密码判断用户是否拥有合法登录权限 27 /// 28 ///
100成功,101账号错误,102密码错误,103参数不合法
29 public async Task
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         ///  24         /// 通过构造涵数方式注入Core层的UserCore实例 25         ///  26         ///  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         ///  43         /// 实现客户端的登录操作 44         ///  45         ///  46         /// 
47 [HttpPost] 48 [AllowAnonymous] 49 public async Task
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     ///  10     /// 重写依赖注入的业务 11     ///  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(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
(); 13 }

  

总结

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

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

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

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

 

声明

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

 

转载于:https://www.cnblogs.com/Miidy/p/9604759.html

你可能感兴趣的文章
4.3.5 Sticks (POJ1011)
查看>>
POJ 2960 S-Nim 博弈论 sg函数
查看>>
Dijkstra模版
查看>>
LinearLayout里面的空间居中对齐
查看>>
5A.炫酷双截棍(C++)
查看>>
ADC取样
查看>>
用户界面分面注意事项
查看>>
POJ 2151 概率DP
查看>>
【C/C++开发】C++编译指令#pragma pack的配对使用
查看>>
苹果iPhone 5C和5S发布后,消费者如何选择?
查看>>
map遍历的三种基础用法
查看>>
bzoj2427: [HAOI2010]软件安装
查看>>
mac快速正确的安装 Ruby, Rails 运行环境
查看>>
cat
查看>>
进程篇
查看>>
深恶痛绝重写setter和getter
查看>>
MySQL via EF6 的试用报告
查看>>
ASP.NET本质论第一章网站应用程序学习笔记3-对象化的Http
查看>>
c++虚函数与重载
查看>>
两个常见问题解决
查看>>