2017-08-06 93 views
1

我正在使用Autofac和ASP.NET Core。Autofac參數化實例化,針對不同參數的不同解決方案

我的依賴是一個Reporter

public class Reporter { 
    public Reporter (bool doLogging) { DoLogging = doLogging ; } 
    public string DoLogging { get; set; } 
    // other stuff 
} 

我需要使用這樣的:

public class Foo 
{ 
    public Foo(Func<bool, Reporter> reporterFactory) { _reporterFactory = reporterFactory; } 
    private readonly Func<bool, Reporter> _reporterFactory; 
} 

而且我希望它來解決這樣的:

_reporterFactory(false) ---> equivalent to ---> new Reporter(false) 
_reporterFactory(true) ---> equivalent to ---> new Reporter(true) 

我想每個請求的相同實例(即Autofac的InstancePerLifetimeScope),對於相同的bool參數。當我多次撥打_reporterFactory(false)時,我想要相同的實例。當我多次撥打_reporterFactory(true)時,我需要相同的實例。但是這兩個實例必須彼此不同。

所以我註冊這樣的:

builder 
    .Register<Reporter>((c, p) => p.TypedAs<bool>() ? new Reporter(true): new Person(false)) 
    .As<Reporter>() 
    .InstancePerLifetimeScope(); // gives "per HTTP request", which is what I need 

然而,當我解決我得到相同的情況下,不管bool說法:

var reporter   = _reporterFactory(false); 
var reporterWithLogging = _reporterFactory(true); 
Assert.That(reporter, Is.Not.SameAs(reporterWithLogging));  // FAIL! 

"Parameterized Instantiation"文檔說

不止一次地解析對象,你會得到相同的對象實例無論您傳入的參數是多少,只要傳遞不同的參數都不會破壞對生命週期範圍的尊重。

這解釋了行爲。那麼如何正確註冊?

+1

http://docs.autofac.org/en/latest/faq/select-by-context.html#option-3-use-keyed-services有幫助嗎? – mjwills

+0

@mjwills嗯我需要看看,我希望我想要的是可能的,我只是使用錯誤的語法或什麼。 – grokky

+1

你的'人'似乎是一個域實體;不是應用程序_component_。 DI容器旨在構建_components_的對象圖。在構建這些對象圖的過程中,不應該存在關於它的依賴關係的歧義,它不包括使用運行時數據,如實體,DTO,視圖模型和其他數據對象。 – Steven

回答

2

正如評論所說,你可以使用服務來實現自己的目標:

builder.Register(c => new Reporter(true)).Keyed<IReporter>(true).InstancePerLifetimeScope(); 
builder.Register(c => new Reporter(false)).Keyed<IReporter>(false).InstancePerLifetimeScope(); 

的事情是,如果你想將其注入到另一個類,你就必須與IIndex<bool, IReporter>注入它:

public class Foo 
{ 
    public Foo(IIndex<bool, IReporter> reporters) 
    { 
     var withLogging = reporters[true]; 
     var withoutLogging = reporters[false]; 
    } 
} 

IIndex是Autofac的接口,這使得你的組件緊耦合與所述容器,而這可能是不期望的。爲了避免這種情況,你可以另外註冊工廠,像這樣:

builder.Register<Func<bool, IReporter>>((c,p) => withLogging => c.ResolveKeyed<IReporter>(withLogging)).InstancePerLifetimeScope(); 

public class Foo 
{ 
    public Foo(Func<bool, IReporter> reporters) 
    { 
     var withLogging = reporters(true); 
     var withoutLogging = reporters(false); 
    } 
} 

現在你有沒有耦合到容器本身的工作解決方案。