AutoFac注册组件---通过参数值选择具体的实现
官方文档链接:Autofac
1. 通过参数值选择具体的实现
builder.Register<ICreditCard>(
(c, p) =>
{
var accountId = p.Named<string>("accountId");
if (accountId.StartsWith("9"))
{
return new GoldCard(accountId);
}
else
{
return new StandardCard(accountId);
}
});
以上代码实现了在运行时指定具体的注册类型,而不是在配置时期指定,增加了灵活性。
但是这种写法不是最优解,如果申明一个创建ICreditCard
实例的委托,和一个委托工厂
,语法可以变得更加干净,类型安全。
委托工厂
工厂适配器将容器的实例化特性提供给托管组件,而不是将容器本身暴露给它们。
如果类型T
在容器中注册,AutoFac将自动解析对Func<T>
的依赖关系,将其作为通过容器创建实例T的工厂。
在使用委托工厂以及使用参数化的Func
则每次调用委托工厂都会得到相同的实例。仅传递不同的参数不会违反对生命周期范围的重视。
以上这一段引用了原文并进行了翻译,为防止翻译出现纰漏 在此附上原文
Lifetime scopes are respected using delegate factories as well as when using Func
通过委托工厂来创建实例
public class Shareholding
{
public delegate Shareholding Factory(string symbol, uint holding);
public Shareholding(string symbol, uint holding)
{
Symbol = symbol;
Holding = holding;
}
public string Symbol { get; private set; }
public uint Holding { get; set; }
}
在以上的代码中Shareholdings
类声明了一个构造函数,并提供了一个委托类型,此委托类型可以间接创造Shareholdings
类,AutoFac利用这个委托类型自动生成一个工厂,并通过容器来访问它来创造实例。
var builder = new ContainerBuilder();
builder.RegisterType<Shareholding>();
var container = builder.Build();
var shareholdingFactory = container.Resolve<Shareholding.Factory>();
var shareholding = shareholdingFactory.Invoke("ABC", 1234);
该工厂是标准委托,可以使用如上所述的Invoke()
或函数语法shareholdingFactory("ABC",1234)
进行调用。
默认情况下,AutoFac按参数名称将委托的参数与构造函数的参数进行匹配。 如果您使用通用Func类型,则Autofac将切换成按类型去匹配参数。
其他部件也可以使用刚才构建的工厂,代码如下
public class Portfolio
{
Shareholding.Factory ShareholdingFactory { get; set; }
IList<Shareholding> _holdings = new List<Shareholding>();
public Portfolio(Shareholding.Factory shareholdingFactory)
{
ShareholdingFactory = shareholdingFactory;
}
public void Add(string symbol, uint holding)
{
_holdings.Add(ShareholdingFactory(symbol, holding));
}
}
为了建立连接,Portfolio
类需要在容器构建之前注册
使用组件
可以通过从容器请求一个Portfolio
实例来使用这些组件,容器会自动匹配Portfolio
的构造参数并注入实例:
var portfolio = container.Resolve<Portfolio>();
portfolio.Add("DEF", 4324);
graph TD
A[构建Portfolio] --> B(构造函数需要参数:Shareholding.Factory)
B --> C(构建Shareholding)
C --> A
F(容器实例化Portfolio的流程)
根据上文提到的如果您使用通用Func类型,则Autofac将切换成按类型去匹配参数
我们可以使用Func<T>
委托来创造工厂,它将通过类型来匹配构造函数的参数。