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

ASP.NET MVC IOC依赖注入之Autofac系列(一)

程序员文章站 2023-10-19 13:17:11
话不多说,直入主题看我们的解决方案结构: 分别对上面的工程进行简单的说明: 1、TianYa.DotNetShare.Model:为demo的实体层 2、TianYa.DotNetShare.Repository:为demo的仓储层即数据访问层 3、TianYa.DotNetShare.Servic ......

话不多说,直入主题看我们的解决方案结构:

ASP.NET MVC IOC依赖注入之Autofac系列(一)

分别对上面的工程进行简单的说明:

1、tianya.dotnetshare.model:为demo的实体层

2、tianya.dotnetshare.repository:为demo的仓储层即数据访问层

3、tianya.dotnetshare.service:为demo的服务层即业务逻辑层

4、tianya.dotnetshare.mvcdemo:为demo的web层项目,mvc框架

约定:本demo的web项目为asp.net web 应用程序(.net framework 4.5) mvc框架,实体层、仓储层、服务层均为.net framework 4.5 类库。

一、实体层

ASP.NET MVC IOC依赖注入之Autofac系列(一)

1、定义一个空接口idependency,后面有妙用,用于一次性注入

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;

namespace tianya.dotnetshare.model
{
    /// <summary>
    /// 空接口,用于一次性注入
    /// </summary>
    public interface idependency
    {
    }
}

2、新建一个学生实体 student

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;

namespace tianya.dotnetshare.model
{
    /// <summary>
    /// 学生类
    /// </summary>
    public class student
    {
        /// <summary>
        /// 学号
        /// </summary>
        public string stuno { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string name { get; set; }

        /// <summary>
        /// 年龄
        /// </summary>
        public int age { get; set; }

        /// <summary>
        /// 性别
        /// </summary>
        public string sex { get; set; }
    }
}

demo中的实体就这样了

二、仓储层

ASP.NET MVC IOC依赖注入之Autofac系列(一)

本demo的仓储层需要引用我们的实体层tianya.dotnetshare.model

为什么选择用仓储,原因很简单,方便我们进行个性化扩展。在数据操作的底层进行其他个性化逻辑处理。

约定:

1、接口的定义放在根目录下,接口的实现类,统一放到impl文件夹,表示实现类目录。

2、每个实体,对应一个仓储的接口和实现类,即有多少个实体,就对应创建多少个接口和实现类。

我们新建一个student的仓储接口 istudentrepository.cs

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;

using tianya.dotnetshare.model;

namespace tianya.dotnetshare.repository
{
    /// <summary>
    /// 学生类仓储层接口
    /// </summary>
    public interface istudentrepository
    {
        /// <summary>
        /// 根据学号获取学生信息
        /// </summary>
        /// <param name="stuno">学号</param>
        /// <returns>学生信息</returns>
        student getstuinfo(string stuno);
    }
}

接着在impl中新建一个student的仓储实现studentrepository.cs

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;

using tianya.dotnetshare.model;

namespace tianya.dotnetshare.repository.impl
{
    /// <summary>
    /// 学生类仓储层
    /// </summary>
    public class studentrepository : istudentrepository, idependency
    {
        /// <summary>
        /// 根据学号获取学生信息
        /// </summary>
        /// <param name="stuno">学号</param>
        /// <returns>学生信息</returns>
        public student getstuinfo(string stuno)
        {
            //数据访问逻辑,此处为了演示就简单些
            var student = new student();
            switch (stuno)
            {
                case "10000":
                    student = new student() { stuno = "10000", name = "张三", sex = "男", age = 20 };
                    break;
                case "10001":
                    student = new student() { stuno = "10001", name = "钱七七", sex = "女", age = 18 };
                    break;
                case "10002":
                    student = new student() { stuno = "10002", name = "李四", sex = "男", age = 21 };
                    break;
                default:
                    student = new student() { stuno = "10003", name = "王五", sex = "男", age = 25 };
                    break;
            }

            return student;
        }
    }
}

该类同时实现了istudentrepository接口和idependency接口,其中实现idependency接口的目的是为了后面的web端进行一次性注入

三、服务层

ASP.NET MVC IOC依赖注入之Autofac系列(一)

本demo的服务层需要引用我们的实体层tianya.dotnetshare.model和我们的仓储层tianya.dotnetshare.repository

服务层与仓储层类似,它属于仓储层的使用者。定义的方式也与仓储层类似,有接口和impl实现目录。

但服务层不需要一个实体对应一个,服务层更多的是按照功能模块进行划分,比如一个登录模块,创建一个loginservice。

为了演示,我们新建一个student的服务层接口istudentservice.cs

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;

using tianya.dotnetshare.model;

namespace tianya.dotnetshare.service
{
    /// <summary>
    /// 学生类服务层接口
    /// </summary>
    public interface istudentservice
    {
        /// <summary>
        /// 根据学号获取学生信息
        /// </summary>
        /// <param name="stuno">学号</param>
        /// <returns>学生信息</returns>
        student getstuinfo(string stuno);
    }
}

接着我们同样在impl中新建一个student的服务层实现studentservice.cs

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;

using tianya.dotnetshare.model;
using tianya.dotnetshare.repository;

namespace tianya.dotnetshare.service.impl
{
    /// <summary>
    /// 学生类服务层
    /// </summary>
    public class studentservice : istudentservice, idependency
    {
        /// <summary>
        /// 定义仓储层学生抽象类对象
        /// </summary>
        protected istudentrepository sturepository;

        /// <summary>
        /// 空构造函数
        /// </summary>
        public studentservice() { }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sturepository">仓储层学生抽象类对象</param>
        public studentservice(istudentrepository sturepository)
        {
            this.sturepository = sturepository;
        }

        /// <summary>
        /// 根据学号获取学生信息
        /// </summary>
        /// <param name="stuno">学号</param>
        /// <returns>学生信息</returns>
        public student getstuinfo(string stuno)
        {
            var stu = sturepository.getstuinfo(stuno);
            return stu;
        }
    }
}

该类同时实现了istudentservice接口和idependency接口,其中实现idependency接口的目的是为了后面的web端进行一次性注入

四、web层

ASP.NET MVC IOC依赖注入之Autofac系列(一)

本demo的web项目需要引用以下几个程序集:

1、tianya.dotnetshare.model 我们的实体层

2、tianya.dotnetshare.service 我们的服务层

3、tianya.dotnetshare.repository 我们的仓储层,正常我们的web项目是不应该使用仓储层的,此处我们引用是为了演示ioc依赖注入

4、autofac 依赖注入基础组件

5、autofac.mvc5 依赖注入mvc5的辅助组件

其中autofac和autofac.mvc5可以从我们的nuget上引用:

ASP.NET MVC IOC依赖注入之Autofac系列(一)

如果从线下已安装的程序包源中找不到我们要的程序集,可以尝试添加我们的程序包源,具体步骤如下:

ASP.NET MVC IOC依赖注入之Autofac系列(一)

ASP.NET MVC IOC依赖注入之Autofac系列(一)

名称:nuget.org
源:https://api.nuget.org/v3/index.json

添加新的包源后点击确定(如果已经有此包源就忽略该步骤)

ASP.NET MVC IOC依赖注入之Autofac系列(一)

依次点击下载以下2个组件

ASP.NET MVC IOC依赖注入之Autofac系列(一)

至此我们所有的工作都已经准备好了,接下来就是重头戏,开始做注入工作了。

 打开我们的global.asax文件进行注入工作

using system;
using system.collections.generic;
using system.linq;
using system.web;
using system.web.mvc;
using system.web.optimization;
using system.web.routing;

using autofac;
using autofac.integration.mvc;
using tianya.dotnetshare.model;
using tianya.dotnetshare.repository.impl;
using tianya.dotnetshare.repository;

namespace tianya.dotnetshare.mvcdemo
{
    public class mvcapplication : system.web.httpapplication
    {
        protected void application_start()
        {
            arearegistration.registerallareas();
            filterconfig.registerglobalfilters(globalfilters.filters);
            routeconfig.registerroutes(routetable.routes);
            bundleconfig.registerbundles(bundletable.bundles);

            autofacregister(); //autofac依赖注入
        }

        /// <summary>
        /// autofac依赖注入
        /// </summary>
        private void autofacregister()
        {
            var builder = new containerbuilder();
            //注册mvc控制器(注册所有到控制器,控制器注入,就是需要在控制器的构造函数中接收对象)
            builder.registercontrollers(typeof(mvcapplication).assembly);
            //构造函数注入,对studentrepository与接口进行注入
            builder.registertype<studentrepository>().as<istudentrepository>();

            //设置依赖解析器
            var container = builder.build();
            dependencyresolver.setresolver(new autofacdependencyresolver(container));
        }
    }
}

至此,我们就完成了依赖注入工作,此方式为构造函数注入,接下来我们来看看控制器里面怎么弄。

using system;
using system.collections.generic;
using system.linq;
using system.web;
using system.web.mvc;

using tianya.dotnetshare.model;
using tianya.dotnetshare.service;
using tianya.dotnetshare.repository;

namespace tianya.dotnetshare.mvcdemo.controllers
{
    public class homecontroller : controller
    {
        /// <summary>
        /// 定义仓储层学生抽象类对象
        /// </summary>
        protected istudentrepository sturepository;

        /// <summary>
        /// 通过构造函数进行注入
        /// 注意:参数是抽象类,而非实现类,因为已经在global.asax中将实现类映射给了抽象类
        /// </summary>
        /// <param name="sturepository">仓储层学生抽象类对象</param>
        public homecontroller(istudentrepository sturepository)
        {
            this.sturepository = sturepository;
        }

        public actionresult index()
        {
            var stu = sturepository.getstuinfo("10000");
            string msg = $"学号:10000,姓名:{stu.name},性别:{stu.sex},年龄:{stu.age}。";
            return content(msg);
        }

        public actionresult about()
        {
            viewbag.message = "your application description page.";

            return view();
        }

        public actionresult contact()
        {
            viewbag.message = "your contact page.";

            return view();
        }
    }
}

至此,完成处理,接下来就是见证奇迹的时刻了,我们访问 /home/index,看看是否能返回学生信息。

ASP.NET MVC IOC依赖注入之Autofac系列(一)

我们可以发现,返回了学生的信息,说明我们注入成功了。

总结:

1、采用的是构造函数注入的方式,在构造函数中初始化赋值。

2、sturepository对象不需要实例化,即不需要new,降低了系统资源的消耗。

3、需要在global.asax中对studentrepository写映射,如果仓储类比较多的时候,就需要写很多了,如何避免,这个在后面的篇幅中会讲解到。

扩展: 上面讲解了构造函数注入的方式,下面扩展属性注入的方式,在global.asax中稍微修改下注入语句即可。

将:

builder.registercontrollers(typeof(mvcapplication).assembly);

改为:

builder.registercontrollers(typeof(mvcapplication).assembly).propertiesautowired();

propertiesautowired:表示允许属性注入。