1

次のコードがあるとします。

public interface IMyContext
{
    string subtype { get; set; }
}

public class MyContext : IMyContext
{
    public string subtype { get; set; }
}

public interface IMyExporter
{
    string Export();
}

public class MyExporterXML : IMyExporter
{
    public string Export()
    {
        return "";
    }
}

public class MyExporterJson : IMyExporter
{
    public string Export()
    {
        return "";
    }
}

public class MyExporterFactory
{
    private IMyContext context;
    public MyExporterFactory(IMyContext context)
    {
        this.context = context;
    }

    public IMyExporter Create()
    {
        switch (context.subtype)
        {
            case "JSON" :
                    return new MyExporterJson();
            default:
                    return new MyExporterXML();
        }
    }
}

public class MyService
{
    private IMyContext context;
    private IMyExporter exporter;
    public MyService(IMyContext context, IMyExporter exporter)
    {
        this.context = context;
        this.exporter = exporter;
    }

    public string Extractdata()
    {
        return exporter.Export();
    }
}

[TestClass]
public class UnitTest2
{
    [TestMethod]
    public void TestMethod1()
    {
        var container = new WindsorContainer();
        container.Register(Component.For<IMyContext>().ImplementedBy<MyContext>());
        container.Register(Component.For<MyExporterFactory>());
        container.Register(Component.For<MyService>());
        container.Register(Component.For<IMyExporter>().UsingFactoryMethod(kernel => kernel.Resolve<MyExporterFactory>().Create()));
        var context = container.Resolve<IMyContext>();
        var service = container.Resolve<MyService>();

        context.subtype = "JSON";

        service.Extractdata();

    }
}

MyService に注入されたエクスポーターを、実際に使用するときに解決する方法はありますか?? すなわち。上記のコードを実行すると、解決されるエクスポーターは MyExporterXML ですが、context.subtype = "JSON" 設定のため、MyExporterJson にしたいのです。ただし、サブタイプが設定される前にエクスポーターが解決されます...

Castle::Windsor にはデリゲートベースのファクトリと呼ばれるものがあることは知っていますが、それを使用する方法がわかりません....

どんな助けでも大歓迎です、TIA

セーレン

4

1 に答える 1

3

TypeFactoryFacility とカスタム ITypedFactoryComponentSelector の組み合わせを使用します。あなたのケースでうまくいくはずの何かがあります。

まず、ファクトリのインターフェイスを作成します。

public interface IMyExporterFactory
{
    IMyExporter GetExporter(IMyContext context);
}

次に、コンテキストのサブタイプを使用してコンポーネント名を決定するカスタマイズされたファクトリ コンポーネント セレクターを使用します (そして、登録を変更してエクスポーターに名前を付けます)。

public class ExporterComponentSelector : DefaultTypedFactoryComponentSelector
{
    protected override string GetComponentName(MethodInfo method, object[] arguments)
    {
        if (method.Name == "GetExporter")
        {
            var context = (IMyContext) arguments[0];
            return context.subtype;
        }

        return base.GetComponentName(method, arguments);
    }
}

TypedFactoryFacility とカスタム セレクターを含む Windsor 登録コードの更新を次に示します (サブタイプに基づいてエクスポーターに名前を付けます)。

var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
    Component.For<IMyExporterFactory>().AsFactory(c => c.SelectedWith(new ExporterComponentSelector())),
    Component.For<IMyExporter>().ImplementedBy<MyExporterJson>().Named("json"),
    Component.For<IMyExporter>().ImplementedBy<MyExporterXML>().Named("xml"),
    Component.For<IMyContext>().ImplementedBy<MyContext>(),
    Component.For<MyService>()
    );

これで、サービスは単純に IMyExporterFactory を受け取り、それを使用してエクスポーターを解決します。

public class MyService
{
    private readonly IMyContext context;
    private readonly IMyExporterFactory exporterFactory;

    public MyService(IMyContext context, IMyExporterFactory exporterFactory)
    {
        this.context = context;
        this.exporterFactory = exporterFactory;
    }

    public string Extractdata()
    {
        var exporter = exporterFactory.GetExporter(context);
        return exporter.Export();
    }
}

コンポーネントが小文字の名前 ("xml"、"json") で登録されている場合は、コードが常に小文字の名前を使用する (または ExporterComponentSelector で context.subtype.ToLower() を使用する) ようにする必要があります。

于 2011-10-07T12:22:44.683 に答える