Autofac在使用上有許多需要注意的小細節,這一次遇到建構式的小地雷,特別紀錄一下。讓下一次在踩到時,可以快速地排除。
當在類別中有使用到Autofac ILifetimeScope時需要特別注意建構式參數。一般來說,如果有需要在類別中使用ILifetimeScope,會在類別建構式中將ILifetimeScope注入
public class TestService : ITestService
{
private ILifetimeScope _lifetimeScope;
public TestService()
{
Console.WriteLine("Construct not have parameter");
}
public TestService(ILifetimeScope lifetimeScope)
{
this._lifetimeScope = lifetimeScope;
Console.WriteLine("Construct have parameter ILifetimeScope");
}
}
這個時候如果還有一個沒有參數的建構式時,就會很容易踩到Autofac在Resolve時,建構式選擇的問題。Autofac的建構式選擇,會以符合最多參數的建構式來創建物件,所以當在註冊類別時,沒有特別指定參數,
public static class AutofacHelper
{
public static IContainer AutofacContainer;
public static void Init()
{
var builder = new ContainerBuilder();
builder.RegisterType<TestService>().As<ITestService>();
AutofacContainer = builder.Build();
}
}
當在Resolve TestServcie時
class Program
{
static void Main(string[] args)
{
AutofacHelper.Init();
var testService = AutofacHelper.AutofacContainer.Resolve<ITestService>();
Console.ReadLine();
}
}
使用的建構式,就會跟自己以為的不一樣,如上述的程式在註冊類別和Resolve時,皆沒有傳入參數。所以應該會使用沒有參數的建構式,但是來看執行結果
Autofac在Resolve時,卻使用了有參數的建構式,通常在實務第一時間發現都會接WTF!!!
哪是為什麼Autofac使用了有參數的建構式呢?問題就在程式中使用了ILifetimeScope,因為這一項參數只要在建構式上有使用,Autofac就會自動傳入。如此一來Autofac自然就使用了有參數的。
那如果希望能夠使用ILifetimeScope,又不想透過建構式傳入時,該怎麼處理呢?
public class TestService : ITestService
{
public ILifetimeScope LifetimeScope;
public TestService()
{
Console.WriteLine("Construct not have parameter");
}
}
public static class AutofacHelper
{
public static IContainer AutofacContainer;
public static void Init()
{
var builder = new ContainerBuilder();
builder.Register<TestService>(p =>
{
var testService = new TestService();
testService._lifetimeScope = p.Resolve<ILifetimeScope>();
return testService;
}).As<ITestService>();
AutofacContainer = builder.Build();
}
}
只需要稍微修改一下將LifetimeScope宣告為Public。在註冊時,改使用Register
結論
Autofac在使用上,地雷還不少。所以特別紀錄一下自己踩到的地雷,尤其是一些小細節,之後如果再踩到可以快速地找到解決方法。
免責聲明:
"文章一定有好壞,文章內容有對有錯,使用前應詳閱公開說明書"