Autofac的简单使用

有关依赖注入的原理这里就不说了,依赖注入的框架比较多,比如:Castle、Unity、Ninject、Autofac、StructureMap、Spring.Net等。最近在项目中使用了Autofac,借此机会进行一些总结,也顺便跟大家讨论一下。Autofac主要用了Autofac.dll,AutoMapper.dll。

举个简单的例子,有一个应用用的数据库是Sql Server,将来不排除要使用Oracle或者是其它数据库。那么我们在开发的时候就要考虑了,将来要换数据库的时候是不是要重新开发?一般我们的做法是,将跟数据库交互的放在接口里,然后用Sql Server、Oracle的相关类去实现该接口,在程序初始化的时候根据数据库去实例化相应的接口。直接贴上代码:

IDatabase接口

public interface IDatabase
    {
        string Name { get; }

        void Select(string commandText);

        void Insert(string commandText);

        void Update(string commandText);

        void Delete(string commandText);
    }
View Code

SqlDatabase类

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));
        }
    }
View Code

OracleDatabase类

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));
        }
    }
View Code

在这里,还新增了DataBase的管理类,避免客户端直接操作IDatabase的实现类。

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);
        }
    }
View Code

下面,我们来看Autofac的使用:

var builder = new ContainerBuilder();
            builder.RegisterType<DatabaseManager>();
            //builder.RegisterType<SqlDatabase>().As<IDatabase>();
            builder.RegisterType<OracleDatabase>().As<IDatabase>();
            using (var container = builder.Build())
            {
                var manager = container.Resolve<DatabaseManager>();
                manager.Search("SELECT * FORM USER");
            }
View Code

如果要用Sql Server数据库,则将builder.RegisterType<OracleDatabase>().As<IDatabase>()改为builder.RegisterType<SqlDatabase>().As<IDatabase>()即可,其它都不变。

不过,有人会问,我直接new一个对象不是更简单么?确实,如果只有一个实现类,用new可能会更简单。但是,一个应用通常会有很多的实现类,如果都用new的话,无疑增加了维护的困难。

我不修改代码可以吗?答案是可以的。你可以通过配置文件来配置,下面增加一个配置:

<configSections>
    <section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/>
  </configSections>
  <autofac defaultAssembly="AutofacDemo">
    <components>
      <component type="AutofacDemo.SqlDatabase, AutofacDemo" service="AutofacDemo.IDatabase"/>
    </components>
  </autofac>
View Code

客户端实现的代码如下:

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");
            }
View Code

同样可以得到相同的结果。

这只是Autofac的简单使用。一个应用会有成千上万个实现类,如果每次使用时都是先注册再获取实现类的话,那用依赖注入就没多大意义了。其实,我们可以做一个公共组件,在程序初始化的时候注册,需要用的时候再获取出来,这样就很方便了。

程序初始化时调用EngineContext.Initialize(false)即可,接下来就可以直接像EngineContext.Current.Resolve<IDatabase>()这样使用了。

https://files.cnblogs.com/files/dengwenbo/AutofacInfrastructure.rar

原文地址:https://www.cnblogs.com/dengwenbo/p/4716582.html