2013-08-28 80 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