当前位置:必发365电子游戏 > 编程 > 这八个程序集引用到你的等级次序中,这里通过操功能户数量来掌握一下
这八个程序集引用到你的等级次序中,这里通过操功能户数量来掌握一下
2019-12-19

记录一丝一毫知识,为了越来越好的劳务后来者!

所谓信赖,即写叁个类的时候,里面供给选拔到此外的类;
分为主动依赖被动依赖,这里经过操成效户数量来了然一下。

生龙活虎、为何接收AutoFac?

早前介绍了Unity和Ninject多个IOC容器,不过发现园子里用AutoFac的日常更为分布,于是捯饬了二日,发掘这几个东东实在是个伟大上的IOC容器~

Autofac是.NET领域最佳盛行的IOC框架之风华正茂,旧事是速度最快的三个:

优点: 

既是它都如此牛X了,我们用它就自然了,所以推举其为IOC的终极解决方案!

生龙活虎、先看看写法的不相同

客户模型主动重视的写法 ↓↓↓

class UserModel {
    function __construct() {
        $this->db = new Database('db1');
    }
}

顾客模型被动正视的写法 ↓↓↓

class UserModel {
    function __construct(Database $db) {
        $this->db = $db;
    }
}

二、AutoFac的使用

第生机勃勃你必需得到AutoFac,这里您能够通过种种艺术加载它,小编那边依然经过VS中的NuGet来加载AutoFac,无论是哪一类艺术,最终的指标正是将 Autofac.dll,Autofac.Configuration.dll 那八个程序集援用到您的品种中。那样在你的花色中,若是想采取AutoFac,只需增加其命名空间援引就能够~

二、为何需求被动信任?

1、AutoFac入门

大家先定义三个数目访谈的接口:

public interface IDAL
{
    void Insert(string commandText);
}

然后用Sql和Oracle二种情势分别完结上述接口,可是这里只是演示而已,所以并未真正去得以完结那多个类,你懂的~

SQL方式:

图片 1

public class SqlDAL : IDAL
{
    public void Insert(string commandText)
    {
        Console.WriteLine("使用sqlDAL添加相关信息");
    }
}

图片 2

Oracle方式:

图片 3

public class OracleDAL : IDAL
{
    public void Insert(string commandText)
    {
        Console.WriteLine("使用OracleDAL添加相关信息");
    }
}

图片 4

下一场注入达成布局函数注入:

图片 5

public class DBManager 
{ 
    IDAL _dal;
    public DBManager(IDAL dal) 
    { 
        _dal= dal;
    }
public void Add(string commandText) 
    { 
        _dal.Insert(commandText); 
    }
}

图片 6

最终要实在到位信赖注入就得AtuoFac上台了:

图片 7

var builder = new ContainerBuilder(); 
builder.RegisterType<DBManager>(); 
builder.RegisterType<SqlDAL>().As<IDAL>(); 
using (var container = builder.Build()) 
{ 
    var manager = container.Resolve<DBManager>(); 
    manager.Add("INSERT INTO Persons VALUES ('Man', '25', 'WangW', 'Shanghai')"); 
}

图片 8

从以上栗子能够看出,其实AutoFac的选拔跟Unity的施用有一点像,关键的东东正是以此Container容器类

先看看主动信赖的动静

class Database {
    public function __construct($name) {
        echo "Linked {$name} Database.n";
    }
}

class UserModel {
    public function __construct() {
        $this->db = new Database('db1');
    }
}

$user = new UserModel();
// 输出 "Linked db1 Database."

如上情况,要是你必要操作别的数据库呢?
就需求把 new Database('db1') 改为 new Database('db2')
那假使是三个库都要操作呢?
思维一下。


2、AutoFac常用艺术求证

再看看被动信赖的景况

class UserModel {
    function __construct(Database $db) {
        $this->db = $db;
    }
}

$user1 = new UserModel(new Database('db1'));
// 输出 Linked db1 Database.
$user2 = new UserModel(new Database('db2'));
// 输出 Linked db2 Database.

没有供给改进 Database 类,就能够访问别的数据库,也许同有时候做客;
下降耦合度
但难题是 UserModel 依然要求传递三个 Database 对象来先河化,要是想改用 Redis 了吗?
心想一下。


(1)builder.RegisterType<Object>().As<Iobject>(卡塔尔国:注册项目及其实例。举例上边正是注册接口IDAL的实例SqlDAL

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<SqlDAL>().As<IDAL>();
IContainer container = builder.Build();
SqlDAL sqlDAL = (SqlDAL)container.Resolve<IDAL>();

三、透彻消除注重关系 IoC容器

说容器在此以前,插播个函数
call_user_func_array
调用回调函数,并把二个数组参数作为回调函数的参数
合法例子:

function foobar($arg, $arg2) {
    echo __FUNCTION__, " got $arg and $arg2n";
}

// Call the foobar() function with 2 arguments
call_user_func_array("foobar", array("one", "two"));

// output:foobar got one and two

接着说 IoC容器

// 定义一个标准接口
interface ModuleInterface {
    public function activate(array $target);
}

// 数据库实现标准接口
class Database implements ModuleInterface {

    public function __construct($name) {
        echo "Linked {$name} Database.n";
    }

    public function activate(array $target) {
        echo "Database activate.n";
    }
}

// 缓存实现标准接口
class Redis implements ModuleInterface {

    public function __construct($name) {
        echo "Linked {$name} Redis.n";
    }

    public function activate(array $target) {
        echo "Redis activate.n";
    }
}

// 用户模型依赖注入接口
class UserModel {
    protected $module;

    public function __construct(ModuleInterface $module) {
        $this->module = $module;
    }

    public function test($arr = []) {
        $this->module->activate($arr);
    }
}

// IoC容器的实现
class Container {
    protected $binds;
    protected $instances;

    // 实现绑定关系
    public function bind($abstract, $concrete) {
        if ($concrete instanceof Closure) {
            $this->binds[$abstract] = $concrete;
        } else {
            $this->instances[$abstract] = $concrete;
        }
    }

    // 生产类对象
    public function make($abstract, $parameters = []) {
        if (isset($this->instances[$abstract])) {
            return $this->instances[$abstract];
        }

        $arr = [$this, $parameters];

        return call_user_func_array($this->binds[$abstract], $arr);
    }
}

// 容器服务
$container = new Container;
// 注册UserModel
$container->bind('user', function($container, $params){
    return new UserModel($container->make($params[0], $params[1]));
});
// 注册Database
$container->bind('database', function($container, $name){
    return new Database($name);
});
// 注册Redis
$container->bind('redis', function($container, $name){
    return new Redis($name);
});

$user1 = $container->make('user', ['database', 'db_master']);
// 这里解释一下调用后具体发生了什么
// step1:调用容器的 make 方法,传入 $abstract, $parameters
// step2:$parameters 在 array_unshift 之后有两个值 [$this, 'database']
// step3:call_user_func_array 回调外面注册过的 UserModel 闭包,并将参数传入
// step4:注册的 UserModel 闭包接收参数,$container 继续调用容器 make 方法
// step5:此时 make 方法收到的参数是 'database',继续回调函数
// step6:返回注册过的 Database 对象依赖注入到 UserModel 中
// step7:最终返回 UserModel 对象
$user1 = $container->make('user', ['database', 'db_master']);
$user1->test([1,2,3]);
$user2 = $container->make('user', ['database', 'db_slave']);
$user3 = $container->make('user', ['redis', '127.0.0.1']);
// output:Linked db_master Database.
// output:Database activate.
// output:Linked db_slave Database.
// output:Linked 127.0.0.1 Redis.

如上输出看出,通过 IoC容器 创立的靶子,不只能够用 Database 来最初化,也得以用 Redis 来初步化。

在容器中,所谓注册,其实就是把闭包(无名函数卡塔尔(英语:State of Qatar)存款和储蓄在八个字典中了,key值就是注册的率先个字符串参数
闭包(无名函数卡塔尔(英语:State of Qatar)又回去了对应的类对象
然后再经过 callback 将依附的对象注入到必要的目的中

当真的 IoC容器 要比那纷纭得多,周详得多,这里仅仅是为着便于精晓其运营机制。

关于代码中关系的 interface ModuleInterface,这几个重大是用来做规范的,就是名门都会写本人的类,那什么标方便调用呢?

(2)IContainer.Resolve<IDAL>(卡塔尔国:分析有个别接口的实例。比如地点的末梢风度翩翩行代码就是深入分析IDAL的实例SqlDAL

(3)builder.RegisterType<Object>().Named<Iobject>(string name卡塔尔:为一个接口注册区别的实例。有的时候候难免会境遇多少个类映射同叁个接口,譬如SqlDAL和OracleDAL都落实了IDAL接口,为了正确获取想要的等级次序,就亟须在注册时起名字。

builder.RegisterType<SqlDAL>().Named<IDAL>("sql");
builder.RegisterType<OracleDAL>().Named<IDAL>("oracle");
IContainer container = builder.Build();
SqlDAL sqlDAL = (SqlDAL)container.ResolveNamed<IDAL>("sql");
OracleDAL oracleDAL = (OracleDAL)container.ResolveNamed<IDAL>("oracle");

(4)IContainer.ResolveNamed<IDAL>(string name卡塔尔(قطر‎:拆解解析有些接口的“命名实例”。比方地点的末梢豆蔻梢头行代码就是拆解剖判IDAL的命名实例OracleDAL

(5)builder.RegisterType<Object>().Keyed<Iobject>(Enum enum卡塔尔(قطر‎:以枚举的法子为贰个接口注册差别的实例。一时候大家会将某叁个接口的两样完成用枚举来分裂,而不是字符串,比如:

public enum DBType{ Sql, Oracle}

builder.RegisterType<SqlDAL>().Keyed<IDAL>(DBType.Sql);
builder.RegisterType<OracleDAL>().Keyed<IDAL>(DBType.Oracle);
IContainer container = builder.Build();
SqlDAL sqlDAL = (SqlDAL)container.ResolveKeyed<IDAL>(DBType.Sql);
OracleDAL oracleDAL = (OracleDAL)container.ResolveKeyed<IDAL>(DBType.Oracle);

(6)IContainer.ResolveKeyed<IDAL>(Enum enum卡塔尔(قطر‎:依照枚举值分析某些接口的一定实例。譬如地点的末尾风姿浪漫行代码正是深入分析IDAL的一定实例OracleDAL

(7)builder.RegisterType<Worker>(卡塔尔国.InstancePerDependency(卡塔尔:用于调控指标的生命周期,每一趟加载实例时都以新建一个实例,暗许正是这种艺术

(8)builder.RegisterType<Worker>(卡塔尔(قطر‎.SingleInstance(卡塔尔:用于调节目标的生命周期,每一遍加载实例时都是重返同多少个实例

(9)IContainer.Resolve<T>(NamedParameter namedParameter卡塔尔(قطر‎:在拆解解析实例T时给其赋值

DBManager manager = container.Resolve<DBManager>(new NamedParameter("name", "SQL"));

图片 9

public class DBManager 
{   
    IDAL dal;
    public DBManager (string name,IDAL  _dal)
    {
        Name = name;
        dal= _dal;
    }
}

图片 10

3、通过安插的办法选取AutoFac

(1)先计划好陈设文件

图片 11

<?xml version="1.0"?>
  <configuration>
    <configSections>
      <section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/>
    </configSections>
    <autofac defaultAssembly="ConsoleApplication1">
      <components>
        <component type="ConsoleApplication1.SqlDAL, ConsoleApplication1" service="ConsoleApplication1.IDAL" />
      </components>
    </autofac>
  </configuration>

图片 12

(2)读取配置达成借助注入(注意引进Autofac.Configuration.dll)

图片 13

static void Main(string[] args)
    {
        ContainerBuilder builder = new ContainerBuilder();
        builder.RegisterType<DBManager>();
        builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
        using (IContainer container = builder.Build())
        {
            DBManager manager = container.Resolve<DBManager>();
            manager.Add("INSERT INTO Persons VALUES ('Man', '25', 'WangW', 'Shanghai')"); 
    } 

图片 14

三、ASP.NET MVC与AtuoFac

算是到了ASP.NET MVC与AtuoFac双剑合璧的时候了,上面就看看AtuoFac在MVC中的应用,其实超粗略,大致就多少个步骤解决:

1、首先在函数Application_Start(卡塔尔国 注册自个儿的主宰器类,必供给引进Autofac.Integration.Mvc.dll

图片 15

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Autofac;
using AtuoFacOfMVC4.Models;
using System.Reflection;
using Autofac.Integration.Mvc;


namespace AtuoFacOfMVC4
{
   public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            var builder = new ContainerBuilder();
            SetupResolveRules(builder);
            builder.RegisterControllers(Assembly.GetExecutingAssembly());
            var container = builder.Build();
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

            AreaRegistration.RegisterAllAreas();
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
        }
        private void SetupResolveRules(ContainerBuilder builder)
        {
            builder.RegisterType<StudentRepository>().As<IStudentRepository>();
        }
    }
}

图片 16

2、曾经在您的MVC程序中流入信任代码就ok了

(1)首先声美赞臣(Meadjohnson卡塔尔(英语:State of Qatar)个Student学子类

图片 17

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace AtuoFacOfMVC4.Models
{
    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Graduation { get; set; }
        public string School { get; set; }
        public string Major { get; set; }
    }
}

图片 18

(2)然后注明仓库储存接口及其达成

图片 19

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AtuoFacOfMVC4.Models
{
    public interface IStudentRepository
    {
        IEnumerable<Student> GetAll();
        Student Get(int id);
        Student Add(Student item);
        bool Update(Student item);
        bool Delete(int id);
    }
}

图片 20

图片 21 View Code

(3)最终增添调整器StudentController,并流入信任代码

图片 22

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using AtuoFacOfMVC4.Models;

namespace AtuoFacOfMVC4.Controllers
{
    public class StudentController : Controller
    {
        readonly IStudentRepository repository;
        //构造器注入
        public StudentController(IStudentRepository repository)
        {
            this.repository = repository;
        }

        public ActionResult Index()
        {
            var data = repository.GetAll();
            return View(data);
        }

    }
}

图片 23

(4)最终为调节器StudentController的Index方法增添视图就能够,这里不再详述,运维效果如下

图片 24

 

我介绍:半路学IT,做开拓3年,先下车在一家分享单车公司,做后台开荒!

这八个程序集引用到你的等级次序中,这里通过操功能户数量来掌握一下。 

 小编开了叁个群众号,款待各位有情趣相投朋友,关心!不许时分享工作,和本身得传说!

 

图片 25

*将协和学习的有限记录并分享出去,不仅可以使和煦获得成长,一时也能帮助一下别人,何乐而不为呢?若是那篇小说对您还或者有一些用的话,希望辅助推荐一下~