.Net IOC框架入门之——Autofac

一、简介

 Autofac是.NET领域最为流行的IOC框架之一,传说是速度最快的一个

目的

1.依赖注入的目的是为了解耦。
2.不依赖于具体类,而依赖抽象类或者接口,这叫依赖倒置。
3.控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。
4. 微软的DependencyResolver如何创建controller

生命周期

1、InstancePerDependency

对每一个依赖或每一次调用创建一个新的唯一的实例。这也是默认的创建实例的方式。官方文档解释:Configure the component so that every dependent component or call to Resolve() gets a new, unique instance (default.) 

2、InstancePerLifetimeScope

在一个生命周期域中,每一个依赖或调用创建一个单一的共享的实例,且每一个不同的生命周期域,实例是唯一的,不共享的。官方文档解释:Configure the component so that every dependent component or call to Resolve() within a single ILifetimeScope gets the same, shared instance. Dependent components in different lifetime scopes will get different instances. 

3、InstancePerMatchingLifetimeScope

在一个做标识的生命周期域中,每一个依赖或调用创建一个单一的共享的实例。打了标识了的生命周期域中的子标识域中可以共享父级域中的实例。若在整个继承层次中没有找到打标识的生命周期域,则会抛出异常:DependencyResolutionException。官方文档解释:Configure the component so that every dependent component or call to Resolve() within a ILifetimeScope tagged with any of the provided tags value gets the same, shared instance. Dependent components in lifetime scopes that are children of the tagged scope will share the parent's instance. If no appropriately tagged scope can be found in the hierarchy an DependencyResolutionException is thrown. 

4、InstancePerOwned

在一个生命周期域中所拥有的实例创建的生命周期中,每一个依赖组件或调用Resolve()方法创建一个单一的共享的实例,并且子生命周期域共享父生命周期域中的实例。若在继承层级中没有发现合适的拥有子实例的生命周期域,则抛出异常:DependencyResolutionException。官方文档解释:Configure the component so that every dependent component or call to Resolve() within a ILifetimeScope created by an owned instance gets the same, shared instance. Dependent components in lifetime scopes that are children of the owned instance scope will share the parent's instance. If no appropriate owned instance scope can be found in the hierarchy an DependencyResolutionException is thrown. 

5、SingleInstance

每一次依赖组件或调用Resolve()方法都会得到一个相同的共享的实例。其实就是单例模式。官方文档解释:Configure the component so that every dependent component or call to Resolve() gets the same, shared instance. 

6、InstancePerHttpRequest  (新版autofac建议使用InstancePerRequest)

在一次Http请求上下文中,共享一个组件实例。仅适用于asp.net mvc开发。

官方文档解释:Share one instance of the component within the context of a single HTTP request.

二、常用方法

(1)builder.RegisterType<Object>().As<Iobject>():注册类型及其实例。例如下面就是注册接口IDAL的实例SqlDAL
(2)IContainer.Resolve<IDAL>():解析某个接口的实例。例如上面的最后一行代码就是解析IDAL的实例SqlDAL
(3)builder.RegisterType<Object>().Named<Iobject>(string name):为一个接口注册不同的实例。有时候难免会碰到多个类映射同一个接口,比如SqlDAL和OracleDAL都实现了IDAL接口,为了准确获取想要的类型,就必须在注册时起名字。
(4)IContainer.ResolveNamed<IDAL>(string name):解析某个接口的“命名实例”。例如上面的最后一行代码就是解析IDAL的命名实例OracleDAL
(5)builder.RegisterType<Object>().Keyed<Iobject>(Enum enum):以枚举的方式为一个接口注册不同的实例。有时候我们会将某一个接口的不同实现用枚举来区分,而不是字符串,
(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时给其赋值

三、简单实例

1)创建一个控制台工程。创建一个数据库操作接口IDatabase.cs:

 public interface IDatabase
    {
        //这里包含CRUD四种操作的方法。
        string Name { get; }
        void Select(string commandText);
        void Insert(string commandText);
        void Update(string commandText);
        void Delete(string commandText);
    }

2)创建两种数据库的操作类,SqlDatabase.cs以及OracleDatabase.cs:

 public class SqlDatabase : IDatabase
    {
        public string Name
        {
            get { return "sqlserver"; }
        }
        public void Select(string commandText)
        {
            Console.WriteLine(string.Format("'{0}' is a query sql in {1}!", commandText, Name));
        }
        public void Insert(string commandText)
        {
            Console.WriteLine(string.Format("'{0}' is a insert sql in {1}!", commandText, Name));
        }
        public void Update(string commandText)
        {
            Console.WriteLine(string.Format("'{0}' is a update sql in {1}!", commandText, Name));
        }
        public void Delete(string commandText)
        {
            Console.WriteLine(string.Format("'{0}' is a delete sql in {1}!", commandText, Name));
        }
    }

 public class OracleDatabase : IDatabase
    {
        public string Name
        {
            get { return "oracle"; }
        }
        public void Select(string commandText)
        {
            Console.WriteLine(string.Format("'{0}' is a query sql in {1}!", commandText, Name));
        }
        public void Insert(string commandText)
        {
            Console.WriteLine(string.Format("'{0}' is a insert sql in {1}!", commandText, Name));
        }
        public void Update(string commandText)
        {
            Console.WriteLine(string.Format("'{0}' is a update sql in {1}!", commandText, Name));
        }
        public void Delete(string commandText)
        {
            Console.WriteLine(string.Format("'{0}' is a delete sql in {1}!", commandText, Name));
        }
    }

3)接着创建一个数据库管理器DatabaseManager.cs:

 public class DatabaseManager
    {
        IDatabase _database;
        public DatabaseManager(IDatabase database)
        {
            _database = database;
        }
        public void Search(string commandText)
        {
            _database.Select(commandText);
        }
        public void Add(string commandText)
        {
            _database.Insert(commandText);
        }
        public void Save(string commandText)
        {
            _database.Update(commandText);
        }
        public void Remove(string commandText)
        {
            _database.Delete(commandText);
        }
    }

4)在控制台中,编写以下测试程序:

        static void Main(string[] args)
        {
            var builder = new ContainerBuilder();
            builder.RegisterType<DatabaseManager>();// 通过ContainerBuilder方法RegisterType对DatabaseManager进行注册
            builder.RegisterType<SqlDatabase>().As<IDatabase>(); //注册类型及其实例。例如下面就是注册接口IDatabase的实例SqlDatabase
            //你修改数据库类型注册为: builder.RegisterType<OracleDatabase>().As<IDatabase>();
            using (var container = builder.Build())
            {
                var manager = container.Resolve<DatabaseManager>();
                manager.Search("SELECT * FORM USER");
            }
            Console.ReadKey();
        }

5)显然以上的程序中,SqlDatabase或者OracleDatabase已经暴露于客户程序中了,现在我想将该类型选择通过文件配置进行读取。

修改App.config:

     var builder = new ContainerBuilder();
            builder.RegisterType<DatabaseManager>();
            builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
            using (var container = builder.Build())
            {
                var manager = container.Resolve<DatabaseManager>();
                manager.Search("SELECT * FORM USER");
            }

            // 另外一种方式
            //var builder = new ContainerBuilder();
            builder.RegisterType<DatabaseManager>();
            //builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
            //builder.Register(c => new DatabaseManager(c.Resolve<IDatabase>()));
            //using (var container = builder.Build())
            //{
            //    var manager = container.Resolve<DatabaseManager>();
            //    manager.Search("SELECT * FORM USER");
            //}

6)现在我想通过一个用户类来控制操作权限,比如增删改的权限,创建一个用户类:

    public interface Identity
    {
        int Id { get; set; }
    }
    public class User : Identity
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

在构造函数中增加了一个参数User,而Add,Save,Remove增加了权限判断。

            User user = new User { Id = 1, Name = "leepy" };
            var builder = new ContainerBuilder();
            builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
            builder.RegisterInstance(user).As<User>();
            builder.Register(c => new DatabaseManager(c.Resolve<IDatabase>(), c.Resolve<User>()));
            using (var container = builder.Build())
            {
                var manager = container.Resolve<DatabaseManager>();
                manager.Add("INSERT INTO USER ...");
            }

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值