2013-08-28 143 views
3

考慮下面的代碼解析如何獲取autofac解決創造這些對我的服務消費方IProcessor
autofac配置(解決已經發生了)

實例?
我需要autofac來使用這個函數,或者類似於這個函數來創建相應項目的相關策略。這些策略需要以正確解決其依賴關係的方式來創建。

理想情況下,這需要發生在應用程序的COMPOSITION ROOT。 下面的代碼不能正確使用容器來構建實例。真實代碼中的StrategyAStrategyB將具有其自己的依賴關係。當消費者被處置時,他們也需要處置。

集裝箱
我試過這個,並得到一個錯誤,說明解析操作已經發生。

var builder = new Autofac.ContainerBuilder(); 
builder.RegisterType<StrategyA>().As<IProcessor>().Keyed<IProcessor>(typeof(ItemA).Name).InstancePerDependency(); 
builder.RegisterType<StrategyB>().As<IProcessor>().Keyed<IProcessor>(typeof(ItemB).Name).InstancePerDependency(); 
builder.Register<Func<string, IProcessor>>(c => (s) => c.ResolveKeyed<IProcessor>(s)); 
builder.RegisterType<MyServiceConsumer>().As<IConsumer>(); 

var container = builder.Build(); 
var consumer = container.Resolve<IConsumer>().DoStuff(new ItemA()).Dump(); 

服務消費者。

public class MyServiceConsumer : IConsumer { 
    Func<string, IProcessor> processor; 
    public MyServiceConsumer(Func<string, IProcessor> processor) { 
     //processor.Dump("px"); 
     this.processor = processor; 
    } 
    public string DoStuff(IItem item) { 
     return processor(item.GetType().Name).ProcessItem(item); 
    } 
} 

這裏有接口​​。

public interface IConsumer { string DoStuff(IItem item); } 
public interface IProcessor { string ProcessItem(IItem item); } 
public interface IItem { string Name { get; } } 
public interface IItemStrategy<in T> : IProcessor where T : IItem { string ProcessItem(T item); } 

下面是具體的類。

public class ItemA : IItem { public string Name { get { return "A"; } } public string UniqueA { get { return "+ UA"; } } } 
public class ItemB : IItem { public string Name { get { return "B"; } } public string UniqueB { get { return "+ UB"; } } } 

戰略的實現。 我希望我能夠正確地應用該模式,理想情況下我確實需要強類型化策略?

public class StrategyA : IItemStrategy<ItemA> { 
    string IProcessor.ProcessItem(IItem item) { Debug.Assert(item is ItemA); return this.ProcessItem((ItemA)item); } 
    public string ProcessItem(ItemA item) { return "PA " + item.Name + item.UniqueA; } 
} 
public class StrategyB : IItemStrategy<ItemB> { 
    string IProcessor.ProcessItem(IItem item) { Debug.Assert(item is ItemB); return this.ProcessItem((ItemB)item); } 
    public string ProcessItem(ItemB item) { return "PB " + item.Name + item.UniqueB; } 
} 

回答

3

我已經想通了。
的提示在這裏autofac registration issue in release v2.4.5.724

var builder = new Autofac.ContainerBuilder(); 
builder.RegisterType<StrategyA>().As<IProcessor>().Keyed<IProcessor>(typeof(ItemA).Name).InstancePerDependency(); 
builder.RegisterType<StrategyB>().As<IProcessor>().Keyed<IProcessor>(typeof(ItemB).Name).InstancePerDependency(); 
builder.Register<Func<string, IProcessor>>(c => { 
    var ctx = c.Resolve<IComponentContext>(); 
    return (s) => ctx.ResolveKeyed<IProcessor>(s); 
}); 
builder.RegisterType<MyServiceConsumer>().As<IConsumer>(); 

var container = builder.Build(); 

var consumer = container.Resolve<IConsumer>().DoStuff(new ItemB()).Dump(); 
+0

每次我註冊一個Func時,都會咬我。幸運的是,異常消息是*非常*描述性的。 –

0

我想你太努力了,以避免你的代碼本身的DI。調用沒有任何問題。解決你的容器。

我將在下面的方法聲明添加到的iItem:

IProcessor GetStrategy(IContainer container); 

添加下面的實現爲意達:

public IProcessor GetStrategy(IContainer container) 
{ 
    return container.Resolve<StrategyA>(); 
} 

及以下執行到ItemB:

public IProcessor GetStrategy(IContainer container) 
{ 
    return container.Resolve<StrategyB>(); 
} 

最後,您將MyServiceConsumer的構造函數更改爲:

public MyServiceConsumer(IItem item, IContainer container) 
{ 
    this.item = item; 
    this.processor = item.GetStrategy(container); 
} 

更改您的來電者在容器中通過,並遠離你去。如果您願意,請將容器靜態以避免傳遞,儘管這可能會影響可測試性。

+0

這不是一個壞的建議,我試圖按照使用成分根的格局。我可能會用同一把錘子擊中太多。 (http://blog.ploeh.dk/2011/07/28/CompositionRoot/)如果容器可以解決依賴關係,它將會非常整潔。 – Jim

+1

我想問題是我的解決方案有一種服務定位器模式,而不是建立該對象的DI基礎設施。 –

+0

我想是的,服務定位器現在是一個反模式,供參考,上師:http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/ – Jim