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 に答える