ASP.NET Core 2.0 使用Autofac实现IOC依赖注入

2018 年 9 月 12 日 DotNet

(点击上方蓝字,可快速关注我们)


来源:Andre-Hub

cnblogs.com/Andre/p/9604759.html


初识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(EB_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”类内将注入代码类注册到项目中就可正常使用了。


看完本文有收获?请转发分享给更多人

关注「DotNet」,提升.Net技能 

登录查看更多
0

相关内容

ASP.NET 是一项微软的技术,是一种使嵌入网页中的脚本可由因特网服务器执行的服务器端脚本技术。 指 Active Server Pages(动态服务器页面),运行于 IIS 之中的程序 。
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
模型优化基础,Sayak Paul,67页ppt
专知会员服务
75+阅读 · 2020年6月8日
算法与数据结构Python,369页pdf
专知会员服务
161+阅读 · 2020年3月4日
基于Web页面验证码机制漏洞的检测
FreeBuf
7+阅读 · 2019年3月15日
使用 Canal 实现数据异构
性能与架构
20+阅读 · 2019年3月4日
官方解读:TensorFlow 2.0 新的功能特性
云头条
3+阅读 · 2019年1月23日
R工程化—Rest API 之plumber包
R语言中文社区
11+阅读 · 2018年12月25日
.NET Core 环境下构建强大且易用的规则引擎
Revealing the Dark Secrets of BERT
Arxiv
4+阅读 · 2019年9月11日
Arxiv
4+阅读 · 2019年8月7日
Arxiv
8+阅读 · 2018年5月21日
Arxiv
3+阅读 · 2018年3月29日
VIP会员
相关资讯
基于Web页面验证码机制漏洞的检测
FreeBuf
7+阅读 · 2019年3月15日
使用 Canal 实现数据异构
性能与架构
20+阅读 · 2019年3月4日
官方解读:TensorFlow 2.0 新的功能特性
云头条
3+阅读 · 2019年1月23日
R工程化—Rest API 之plumber包
R语言中文社区
11+阅读 · 2018年12月25日
.NET Core 环境下构建强大且易用的规则引擎
Top
微信扫码咨询专知VIP会员