3

给定以下解决实例的代码IProcessor

如何让 autofac 为我的服务使用者解决和创建这些问题?
我需要 autofac 来使用这个函数,或者类似于这个函数的东西来为相应的项目创建相关的策略。需要以正确解决它们的依赖关系的方式创建这些策略。

理想情况下,这需要在COMPOSITION ROOT应用程序中发生。下面的代码没有正确使用容器来构建实例。StrategyA并且StrategyB在实际代码中会有自己的依赖项。当消费者被处置时,它们也需要被处置。

容器
我已经尝试过这个,并且得到一个错误,说解析操作已经发生。

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; } 
}
4

2 回答 2

3

我已经想通了。
提示是版本 v2.4.5.724 中的 autofac 注册问题

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();
于 2013-08-28T12:38:18.660 回答
0

我认为您正在努力避免代码本身内部的 DI。调用 .Resolve 关闭您的容器没有任何问题。

我会将以下方法声明添加到 IItem:

IProcessor GetStrategy(IContainer container);

将以下实现添加到 ItemA 中:

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);
}

更改您的呼叫者以传递容器,然后离开。如果您愿意,可以将容器设为静态以避免传递它,尽管这可能会影响可测试性。

于 2013-08-28T08:58:01.747 回答