ASP.NET Core2使用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官方网站:https://autofac.org/
Autofac官方的中文文档网站:https://autofaccn.readthedocs.io/zh/latest/
背景
在我们大部分的项目中都会将代码抽成多层,每层之间通过相互依赖串联工作。在这里,我们将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”接口,代码如下:
using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; namespace Lezhima.Data.Interface { public interface IRepository<T> where T : class { /// <summary> /// 从指定的表中获取符合条件的一条实体数据 /// </summary> /// <param name="predicate"></param> /// <returns></returns> Task<T> GetAsync(Expression<Func<T, bool>> predicate); } }
3、在Lezhima.Data层再增加一个名为“Repository”类,实现“IRepository”接口,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; using System.Data.SqlClient; using Lezhima.Data.Interface; namespace Lezhima.Data { /// <summary> /// 数据层 /// 实现IRepository接口 /// </summary> /// <typeparam name="T"></typeparam> public class Repository<T> : IRepository<T> where T : class { /// <summary> /// 从指定的表中获取符合条件的一条实体数据 /// </summary> /// <param name="predicate"></param> /// <returns></returns> public async Task<T> GetAsync(Expression<Func<T, bool>> predicate) { using (var db = new LezhimaContext()) { if (predicate == null) return null; return await db.Set<T>().Where(predicate).FirstOrDefaultAsync<T>(); } } } }
4、在Lezhima.Core层再定义一个名为“IUserCore”接口,代码如下:
using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; namespace Lezhima.Core.Interface { public interface IUserCore { /// <summary> /// 根据账号密码判断用户是否拥有合法登录权限 /// </summary> /// <param name="email"></param> /// <returns>100成功,101账号错误,102密码错误,103参数不合法</returns> Task<MobiResult> Login(string email,string pwd); } }
5、在Lezhima.Core层再增加一个名为“UserCore”类,实现“IUserCore”接口,代码如下:
using Lezhima.Core.Interface; using Lezhima.Data.Interface; using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; namespace Lezhima.Core { public class UserCore : IUserCore { //定义一个依赖属性 private readonly IRepository<EB_User> _Repository; /// <summary> /// 通过构造涵数方式注入Data层的Repository实例 /// </summary> /// <param name="repository"></param> public UserCore(IRepository<EB_User> repository) { _Repository = repository; } /// <summary> /// 根据账号密码判断用户是否拥有合法登录权限 /// </summary> /// <returns>100成功,101账号错误,102密码错误,103参数不合法</returns> public async Task<MobiResult> Login(string email, string pwd) { if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(pwd)) return new MobiResult(103); //到Data层去取指定用户的数据 var model= await _Repository.GetAsync(p => p.Email.Equals(email)&&p.IsDelete!=99); if(model ==null) return new MobiResult(101); if(!model.Pwd.Equals(pwd)) return new MobiResult(102); return new MobiResult(100); } } }
6、在Lezhima.Web层增加一个名为“AccountController ”的控制器,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Lezhima.Core.Interface; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace Lezhima.Web.Controllers { [Authorize] [AutoValidateAntiforgeryToken] public class AccountController : Controller { //定义一个依赖属性 private readonly IUserCore _UserCore; /// <summary> /// 通过构造涵数方式注入Core层的UserCore实例 /// </summary> /// <param name="__UserCore"></param> public AccountController(IUserCore __UserCore) { _UserCore = __UserCore; } // GET: Account public ActionResult Index() { return View(); } /// <summary> /// 实现客户端的登录操作 /// </summary> /// <param name="loginRequest"></param> /// <returns></returns> [HttpPost] [AllowAnonymous] public async Task<IActionResult> Login(LoginRequest loginRequest) { var result = await _UserCore.Login(loginRequest.Email, loginRequest.Pwd); if (result.Code != 100) { ViewBag.ResultModel = result; return View(); } //向客户端写入用户的身份cookie var _user = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { new Claim("UserId", user_model.UserId.ToString()), }, CookieAuthenticationDefaults.AuthenticationScheme)); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, _user); if (string.IsNullOrWhiteSpace(loginRequest.ReturnUrl)) { return RedirectToAction("Index", "Home"); } return Redirect(loginRequest.ReturnUrl); } } }
7、在Lezhima.Web层增加一个名为“Evolution”的类,用于继承Autofac的Module类,实现上述三层之间的依赖关系注入,代码如下:
using Autofac; using Lezhima.Core; using Lezhima.Data; using Lezhima.Data.Interface; using System; namespace Lezhima.Web.Injection { /// <summary> /// 重写依赖注入的业务 /// </summary> public class Evolution : Module { protected override void Load(ContainerBuilder builder) { //注入Data层的Repository类 builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerDependency(); //批量注入Core层的类 builder.RegisterAssemblyTypes(typeof(UserCore).Assembly) .Where(t => t.Name.EndsWith("Core")) .AsImplementedInterfaces(); } } }
8、在Lezhima.Web层的“Startup”类的“ConfigureServices”方法内注入即可,代码如下:
public IConfiguration Configuration { get; } public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddMvc(); //将Evolution注册到项目中来,实现依赖注入 var builder = new ContainerBuilder(); builder.RegisterModule(new Evolution()); builder.Populate(services); var container = builder.Build(); return container.Resolve<IServiceProvider>(); }
总结
1、每层在调用时,通过在该类内声明一个接口类型的属性(变量),再通过Autofac构造涵数注入方式实现依赖注入并获取到相应的类实例。
2、通过继承Autofac的Module类,并在Load方法内重写自已项目的类关系来实现注入业务。
3、Autofac注入有多种不同的生命周期类型,分别为InstancePerLifetimeScope、SingleInstance、InstancePerDependency等,各位在项目中按需选择即可。
4、最后再通过在ASP.NET Core项目内的“Startup”类内将注入代码类注册到项目中就可正常使用了。
声明
本文为作者原创,转载请备注出处与保留原文地址,谢谢。如文章能给您带来帮助,请点下推荐或关注,感谢您的支持!
ASP.NET Core2使用Autofac实现IOC依赖注入竟然能如此的优雅简便的更多相关文章
- ASP.NET Core2使用Autofac实现IOC依赖注入竟然能如此的优雅简便(转载)
原文地址:https://www.cnblogs.com/Andre/p/9604759.html 初识ASP.NET Core的小伙伴一定会发现,其几乎所有的项目依赖都是通过依赖注入方式进行链式串通 ...
- ASP.NET MVC IOC依赖注入之Autofac系列(二)- WebForm当中应用
上一章主要介绍了Autofac在MVC当中的具体应用,本章将继续简单的介绍下Autofac在普通的WebForm当中的使用. PS:目前本人还不知道WebForm页面的构造函数要如何注入,以下在Web ...
- ASP.NET MVC IOC依赖注入之Autofac系列(一)- MVC当中应用
话不多说,直入主题看我们的解决方案结构: 分别对上面的工程进行简单的说明: 1.TianYa.DotNetShare.Model:为demo的实体层 2.TianYa.DotNetShare.Repo ...
- .NET领域最为流行的IOC框架之一Autofac WebAPI2使用Autofac实现IOC属性注入完美解决方案 AutoFac容器初步
.NET领域最为流行的IOC框架之一Autofac 一.前言 Autofac是.NET领域最为流行的IOC框架之一,微软的Orchad开源程序使用的就是Autofac,Nopcommerce开源程 ...
- ASP.NET MVC中使用Unity进行依赖注入的三种方式
在ASP.NET MVC中使用Unity进行依赖注入的三种方式 2013-12-15 21:07 by 小白哥哥, 146 阅读, 0 评论, 收藏, 编辑 在ASP.NET MVC4中,为了在解开C ...
- IOC依赖注入简单实例
转自:http://hi.baidu.com/xyz136299110/item/a32be4269e9d0c55c38d59e6 相信大家看过相当多的IOC依赖注入的例子. 但大家在没有明白原理的情 ...
- IoC 依赖注入容器 Unity
原文:IoC 依赖注入容器 Unity IoC 是什么? 在软件工程领域,“控制反转(Inversion of Control,缩写为IoC)”是一种编程技术,表述在面向对象编程中,可描述为在编译时静 ...
- springboot启动流程(九)ioc依赖注入
所有文章 https://www.cnblogs.com/lay2017/p/11478237.html 正文 在前面的几篇文章中,我们多次提到这么一个转化过程: Bean配置 --> Bean ...
- Spring-DI控制反转和IOC依赖注入
Spring-DI控制反转和IOC依赖注入 DI控制反转实例 IDEAJ自动导入Spring框架 创建UserDao.java接口 public interface UserDao { public ...
随机推荐
- postman tests实例记录(还没看,一些常用的)
这段时间准备测试api接口,postman这个工具很是方便,特别是里面的tests的javascript脚本. 记录一下测试接口常用的tests验证的实例. 1.设置环境变量 postman.setE ...
- charles 小米手机安装Charles证书
1.手机Wi-Fi设置手动代理,添加IP和端口号 此处是:192.168.63.143:8888, 2.保存证书,PC端访问 chls.pro/ssl 下载pem证书,发送到手机 adb push c ...
- 自动手动随便你 Win7驱动程序安装自己设
Win7系统是非常智能方便的操作系统,可以自动安装硬件驱动程序,为用户提供了很多方便.但是并不是所有的驱动程序和硬件都能完美兼容,如果不合适就需要卸载了重新安装:还有一些朋友就习惯自己安装驱动,那么, ...
- Hive常用函数
字符串函数 字符串长度函数:length 语法: length(string A) 返回值: int 说明:返回字符串A的长度 举例: hive> select length(‘abcedfg’ ...
- POJ 2777-题解
一.题意 给你一排N个格子,M种颜色,P个操作.有两种操作:(1)C A B D:把[A, B]区间内的所有格子涂成颜色D.(2)P A B:输出[A, B]区间内的颜色的种类数.注意,初始颜色为1. ...
- PyQt5系列教程(四)信号和槽
软硬件环境 OS X EI Capitan Python 3.5.1 PyQt 5.5.1 前言 信号(Signal)和槽(Slot)是Qt编程中对象间通讯的机制.在Qt中,每一个QObject对象, ...
- uva-10596-欧拉回路
并不要求所有点都联通,只要出现的所有边能形成欧拉回路就行了 做成有向图的欧拉回路wa成了狗 #include <iostream> #include<memory.h> #in ...
- Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? 是由 ...
- VsCode中vim插件剪切板等问题
剪切板共享 这个挺重要的,否则每次右键菜单复制粘贴会奔溃的. 在用户设置中添加: "vim.useSystemClipboard": true, 光标的变化 我觉得这个也重要,毕竟 ...
- 跟我学算法-opencv加载,修改,保存
#include<opencv2/opencv.hpp> #include<iostream> #include<math.h> using namespace c ...