前段时间一直在研究NopCommerce的最新版源代码,NopCommerce在以前的版本中(CodeBehind)是使用Microsoft Enterprise Library的Unity2.0的注入模式,

在全部改版采用MVC的版本中已经使用了号称"注入神器"的Atuofac来进行依赖注入.趁此机会本人也研究了一把Autofac,发现在确实还不错,所以在此记录一下自己的一些学习代码吧.

 

直接上代码,下面的代码部分从网上拷过来,后经过自己进行加工,先来个简单的:

隐藏行号 复制代码 这是一段程序代码。
  1. public interface IDatabase
    
  2. {
    
  3.    void Instance(string commandText);
    
  4. }
    

  5. public class OracleDatabase : IDatabase
    
  6. {
    
  7.    string _commandText;
    
  8.    public void Instance(string commandText)
    
  9.    {
    
  10.       _commandText = commandText;
    
  11.    }
    
  12. }
    

  13. public class SqlDatabase : IDatabase
    
  14. {
    
  15.    string _commandText;
    
  16.    public void Instance(string commandText)
    
  17.    {
    
  18.       _commandText = commandText;
    
  19.    }
    
  20. }
    

隐藏行号 复制代码 这是一段程序代码。
  1. public void Run()
    
  2. {
    
  3.    var builder = new ContainerBuilder();
    
  4.    builder.RegisterType<SqlDatabase>().As<IDatabase>();
    
  5.    using (var container = builder.Build())
    
  6.    {
    
  7.       var dataBase = container.Resolve<IDatabase>();
    
  8.       dataBase.Instance("SELECT * FORM USER");
    
  9.       Console.Write(string.Format("Type:{0}", dataBase.GetType().ToString()));
    
  10.       Console.Read();
    
  11.    }
    
  12. }
    

运行上述程序,实例化SqlDatabase

image

继续来个比上面稍复杂的

隐藏行号 复制代码 这是一段程序代码。
  1. public void Run()
    
  2. {
    
  3.    var builder = new ContainerBuilder();
    

  4.    builder.RegisterType<SqlDatabase>().As<IDatabase>().Keyed<IDatabase>("SqlDatabase");
    
  5.    builder.RegisterType<OracleDatabase>().As<IDatabase>().Keyed<IDatabase>("OracleDatabase"); 
    

  6.    using (var container = builder.Build())
    
  7.    {
    
  8.       var dataBase = container.Resolve<IDatabase>(ResolvedParameter.ForKeyed<IDatabase>("OracleDatabase"));
    
  9.       dataBase.Instance("SELECT * FORM USER");
    
  10.       Console.Write(string.Format("Type:{0}", dataBase.GetType().ToString()));
    
  11.       Console.Read();
    
  12.    }
    
  13. }
    

运行上述程序,实例化OracleDatabase,另外将Keyed换成另外一种写法Named,我测了下效果一样.

 image

 

继续来下面的

隐藏行号 复制代码 这是一段程序代码。
  1. public class DatabaseManager
    
  2. {
    
  3.    IDatabase _database;
    
  4.    string _commandText;
    

  5.    public DatabaseManager(IDatabase database)
    
  6.    {
    
  7.       _database = database;
    
  8.    }
    

  9.    public DatabaseManager(IDatabase database, string commandText)
    
  10.    {
    
  11.       _database = database;
    
  12.       _commandText = commandText;
    
  13.    }
    

  14.    public void Search(string commandText)
    
  15.    {
    
  16.       _database.Instance(commandText);
    
  17.       Console.Write(string.Format("Type:{0}", _database.GetType().ToString()));
    
  18.    }
    

  19.    public void Search()
    
  20.    {
    
  21.       _database.Instance(_commandText);
    
  22.       Console.Write(string.Format("Type:{0}", _database.GetType().ToString()));
    
  23.    }
    
  24. }
    

隐藏行号 复制代码 这是一段程序代码。
  1. public void Run()
    
  2. {
    
  3.    var builder = new ContainerBuilder();
    

  4.    builder.RegisterType<SqlDatabase>().As<IDatabase>().Named<IDatabase>("SqlDatabase");
    
  5.    builder.RegisterType<OracleDatabase>().As<IDatabase>().Named<IDatabase>("OracleDatabase");
    
  6.    builder.RegisterType<DatabaseManager>().WithParameter(ResolvedParameter.ForNamed<IDatabase>("SqlDatabase"));
    

  7.    using (var container = builder.Build())
    
  8.    {
    
  9.       var dataBase = container.Resolve<DatabaseManager>();
    
  10.       dataBase.Search("SELECT * FORM USER");            
    
  11.       Console.Read();
    
  12.    }
    
  13. }
    

运行上述程序,实例化SqlDatabase

image

 

在DatabaseManager类中看到了有两个构造函数,其中一个只传IDatabase,另外一个除IDatabase,还要传一个字符串,那我在注入时需要构造多参数的怎么办,继续

隐藏行号 复制代码 这是一段程序代码。
  1. public void Run()
    
  2. {
    
  3.    var builder = new ContainerBuilder();
    

  4.    builder.RegisterType<SqlDatabase>().As<IDatabase>().Named<IDatabase>("SqlDatabase");
    
  5.    builder.RegisterType<OracleDatabase>().As<IDatabase>().Named<IDatabase>("OracleDatabase");
    
  6.    builder.RegisterType<DatabaseManager>().WithParameter(ResolvedParameter.ForNamed<IDatabase>("OracleDatabase"))
    
  7.                                           .WithParameter(new NamedParameter("commandText", "commandText"));
    

  8.    using (var container = builder.Build())
    
  9.    {
    
  10.       var dataBase = container.Resolve<DatabaseManager>();
    
  11.       dataBase.Search("SELECT * FORM USER");            
    
  12.       Console.Read();
    
  13.    }
    
  14. }
    

运行上述程序后,实例化OracleDatabase,

image

下面再来个泛型的注册,泛型不细讲了,使用方式跟普通类型相若,只是告诉大家如何使用.

隐藏行号 复制代码 这是一段程序代码。
  1. public void Run()
    
  2. {
    
  3.    var builder = new ContainerBuilder();
    

  4.    builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>));
    
  5.    using (var container = builder.Build())
    
  6.    {
    
  7.       var repository = container.Resolve(typeof(IRepository<Customer>));
    
  8.       Console.Write(string.Format("Type:{0}", repository.GetType().ToString()));
    
  9.       Console.Read();
    
  10.    }
    
  11. }
    

运行程序看下

 image

 

在Autofac中除了较常使用的RegisterType来注册外,还可以使用Register来进行注入. 下面来个稍复杂的

隐藏行号 复制代码 这是一段程序代码。
  1. public abstract class BaseDataProviderManager
    
  2.  {
    
  3.     protected BaseDataProviderManager(DataSettings settings)
    
  4.     {
    
  5.        if (settings == null)
    
  6.           throw new ArgumentNullException("settings");
    
  7.        this.Settings = settings;
    
  8.     }
    
  9.     protected DataSettings Settings { get; private set; }
    
  10.     public abstract IDataProvider LoadDataProvider();
    
  11.  }
    

  12.  public class EfDataProviderManager : BaseDataProviderManager
    
  13.  {
    
  14.     public EfDataProviderManager(DataSettings settings)
    
  15.        : base(settings)
    
  16.     {
    

  17.     }
    

  18.     public override IDataProvider LoadDataProvider()
    
  19.     {
    
  20.        var providerName = Settings.DataProvider;
    
  21.        if (String.IsNullOrWhiteSpace(providerName))
    
  22.           throw new Exception("Data Settings doesn't contain a providerName");
    

  23.        switch (providerName.ToLowerInvariant())
    
  24.        {
    
  25.           case "sqlserver":
    
  26.              return new SqlServerDataProvider();
    
  27.           default:
    
  28.              throw new Exception(string.Format("Not supported dataprovider name: {0}", providerName));
    
  29.        }
    
  30.     }
    
  31.  }
    

  32.  public interface IDataProvider
    
  33.  {
    

  34.  }
    

  35.  public class SqlServerDataProvider : IDataProvider
    
  36.  {
    

  37.  }
    

  38.  public class DataSettings
    
  39.  {
    
  40.     public string DataProvider { get; set; }
    
  41.  }
    

 

隐藏行号 复制代码 这是一段程序代码。
  1. public void Run()
    
  2. {
    
  3.    var builder = new ContainerBuilder();
    

  4.    builder.Register(c => new DataSettings() { DataProvider = "sqlserver" }).As<DataSettings>();
    
  5.    builder.Register(x => new EfDataProviderManager(x.Resolve<DataSettings>())).As<BaseDataProviderManager>();
    
  6.    builder.Register(x => (IDataProvider)x.Resolve<BaseDataProviderManager>().LoadDataProvider()).As<IDataProvider>();
    

  7.    using (var container = builder.Build())
    
  8.    {
    
  9.       var dataProvider = container.Resolve<IDataProvider>();
    
  10.       Console.Write(string.Format("Type:{0}", dataProvider.GetType().ToString()));
    
  11.       Console.Read();
    
  12.    }
    
  13. }
    

运行结果大家看下:

image

 

基本上Autofac实际使用中上述能够用了,更多更复杂的,大家需要在工作自己研究了.

 

 

 

posted on 2013-12-06 16:49  tzj19810812  阅读(819)  评论(1编辑  收藏  举报