前段时间一直在研究NopCommerce的最新版源代码,NopCommerce在以前的版本中(CodeBehind)是使用Microsoft Enterprise Library的Unity2.0的注入模式,
在全部改版采用MVC的版本中已经使用了号称"注入神器"的Atuofac来进行依赖注入.趁此机会本人也研究了一把Autofac,发现在确实还不错,所以在此记录一下自己的一些学习代码吧.
直接上代码,下面的代码部分从网上拷过来,后经过自己进行加工,先来个简单的:
-
public interface IDatabase
-
{
-
void Instance(string commandText);
-
}
-
-
public class OracleDatabase : IDatabase
-
{
-
string _commandText;
-
public void Instance(string commandText)
-
{
-
_commandText = commandText;
-
}
-
}
-
-
public class SqlDatabase : IDatabase
-
{
-
string _commandText;
-
public void Instance(string commandText)
-
{
-
_commandText = commandText;
-
}
-
}
-
-
public void Run()
-
{
-
var builder = new ContainerBuilder();
-
builder.RegisterType<SqlDatabase>().As<IDatabase>();
-
using (var container = builder.Build())
-
{
-
var dataBase = container.Resolve<IDatabase>();
-
dataBase.Instance("SELECT * FORM USER");
-
Console.Write(string.Format("Type:{0}", dataBase.GetType().ToString()));
-
Console.Read();
-
}
-
}
-
运行上述程序,实例化SqlDatabase
继续来个比上面稍复杂的
-
public void Run()
-
{
-
var builder = new ContainerBuilder();
-
-
builder.RegisterType<SqlDatabase>().As<IDatabase>().Keyed<IDatabase>("SqlDatabase");
-
builder.RegisterType<OracleDatabase>().As<IDatabase>().Keyed<IDatabase>("OracleDatabase");
-
-
using (var container = builder.Build())
-
{
-
var dataBase = container.Resolve<IDatabase>(ResolvedParameter.ForKeyed<IDatabase>("OracleDatabase"));
-
dataBase.Instance("SELECT * FORM USER");
-
Console.Write(string.Format("Type:{0}", dataBase.GetType().ToString()));
-
Console.Read();
-
}
-
}
-
运行上述程序,实例化OracleDatabase,另外将Keyed换成另外一种写法Named,我测了下效果一样.
继续来下面的
-
public class DatabaseManager
-
{
-
IDatabase _database;
-
string _commandText;
-
-
public DatabaseManager(IDatabase database)
-
{
-
_database = database;
-
}
-
-
public DatabaseManager(IDatabase database, string commandText)
-
{
-
_database = database;
-
_commandText = commandText;
-
}
-
-
public void Search(string commandText)
-
{
-
_database.Instance(commandText);
-
Console.Write(string.Format("Type:{0}", _database.GetType().ToString()));
-
}
-
-
public void Search()
-
{
-
_database.Instance(_commandText);
-
Console.Write(string.Format("Type:{0}", _database.GetType().ToString()));
-
}
-
}
-
-
public void Run()
-
{
-
var builder = new ContainerBuilder();
-
-
builder.RegisterType<SqlDatabase>().As<IDatabase>().Named<IDatabase>("SqlDatabase");
-
builder.RegisterType<OracleDatabase>().As<IDatabase>().Named<IDatabase>("OracleDatabase");
-
builder.RegisterType<DatabaseManager>().WithParameter(ResolvedParameter.ForNamed<IDatabase>("SqlDatabase"));
-
-
using (var container = builder.Build())
-
{
-
var dataBase = container.Resolve<DatabaseManager>();
-
dataBase.Search("SELECT * FORM USER");
-
Console.Read();
-
}
-
}
-
运行上述程序,实例化SqlDatabase
在DatabaseManager类中看到了有两个构造函数,其中一个只传IDatabase,另外一个除IDatabase,还要传一个字符串,那我在注入时需要构造多参数的怎么办,继续
-
public void Run()
-
{
-
var builder = new ContainerBuilder();
-
-
builder.RegisterType<SqlDatabase>().As<IDatabase>().Named<IDatabase>("SqlDatabase");
-
builder.RegisterType<OracleDatabase>().As<IDatabase>().Named<IDatabase>("OracleDatabase");
-
builder.RegisterType<DatabaseManager>().WithParameter(ResolvedParameter.ForNamed<IDatabase>("OracleDatabase"))
-
.WithParameter(new NamedParameter("commandText", "commandText"));
-
-
using (var container = builder.Build())
-
{
-
var dataBase = container.Resolve<DatabaseManager>();
-
dataBase.Search("SELECT * FORM USER");
-
Console.Read();
-
}
-
}
-
运行上述程序后,实例化OracleDatabase,
下面再来个泛型的注册,泛型不细讲了,使用方式跟普通类型相若,只是告诉大家如何使用.
-
public void Run()
-
{
-
var builder = new ContainerBuilder();
-
-
builder.RegisterGeneric(typeof(EfRepository<>)).As(typeof(IRepository<>));
-
using (var container = builder.Build())
-
{
-
var repository = container.Resolve(typeof(IRepository<Customer>));
-
Console.Write(string.Format("Type:{0}", repository.GetType().ToString()));
-
Console.Read();
-
}
-
}
-
运行程序看下
在Autofac中除了较常使用的RegisterType来注册外,还可以使用Register来进行注入. 下面来个稍复杂的
-
public abstract class BaseDataProviderManager
-
{
-
protected BaseDataProviderManager(DataSettings settings)
-
{
-
if (settings == null)
-
throw new ArgumentNullException("settings");
-
this.Settings = settings;
-
}
-
protected DataSettings Settings { get; private set; }
-
public abstract IDataProvider LoadDataProvider();
-
}
-
-
public class EfDataProviderManager : BaseDataProviderManager
-
{
-
public EfDataProviderManager(DataSettings settings)
-
: base(settings)
-
{
-
-
}
-
-
public override IDataProvider LoadDataProvider()
-
{
-
var providerName = Settings.DataProvider;
-
if (String.IsNullOrWhiteSpace(providerName))
-
throw new Exception("Data Settings doesn't contain a providerName");
-
-
switch (providerName.ToLowerInvariant())
-
{
-
case "sqlserver":
-
return new SqlServerDataProvider();
-
default:
-
throw new Exception(string.Format("Not supported dataprovider name: {0}", providerName));
-
}
-
}
-
}
-
-
public interface IDataProvider
-
{
-
-
}
-
-
public class SqlServerDataProvider : IDataProvider
-
{
-
-
}
-
-
public class DataSettings
-
{
-
public string DataProvider { get; set; }
-
}
-
-
public void Run()
-
{
-
var builder = new ContainerBuilder();
-
-
builder.Register(c => new DataSettings() { DataProvider = "sqlserver" }).As<DataSettings>();
-
builder.Register(x => new EfDataProviderManager(x.Resolve<DataSettings>())).As<BaseDataProviderManager>();
-
builder.Register(x => (IDataProvider)x.Resolve<BaseDataProviderManager>().LoadDataProvider()).As<IDataProvider>();
-
-
using (var container = builder.Build())
-
{
-
var dataProvider = container.Resolve<IDataProvider>();
-
Console.Write(string.Format("Type:{0}", dataProvider.GetType().ToString()));
-
Console.Read();
-
}
-
}
-
运行结果大家看下:
基本上Autofac实际使用中上述能够用了,更多更复杂的,大家需要在工作自己研究了.