延迟/懒惰的决心

发布于 2024-12-07 21:55:21 字数 2161 浏览 1 评论 0原文

给出以下代码:

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 中注入的导出器在实际使用时解析? IE。运行上面的代码时,解析的导出器是 MyExporterXML,但我真的希望它是 MyExporterJson,因为 context.subtype = "JSON" 设置。然而,导出器在设置子类型之前已解决...

我知道 Castle::Windsor 有一种称为基于委托的工厂的东西,但我根本不知道如何使用它...

任何帮助将不胜感激,蒂亚·

索伦

Given the following code:

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

    }
}

Is there a way to have the injected exporter in the MyService resolved at the time where it's actually used ?? Ie. when running the above code, the exporter resolved is the MyExporterXML, but I really want's it to be the MyExporterJson because of the context.subtype = "JSON" setting. However the exporter is resolved before the subtype is set...

I know Castle::Windsor has something called delegate-based factories, but I simply can't figure out how to use it....

Any help would be greatly appreciated, TIA

Søren

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

她比我温柔 2024-12-14 21:55:21

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

这是对 Windsor 注册代码的更新,其中包括TypedFactoryFacility 和自定义选择器(它根据子类型命名您的导出器):

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() )。

Use a combination of TypeFactoryFacility and a custom ITypedFactoryComponentSelector. Here's something that should work in your case.

First, create an interface for the factory:

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

Next, use a customized factory component selector that will use the context's subtype to determine the component name (and change the registration to name your exporters):

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

Here's an update to your Windsor registration code that includes the TypedFactoryFacility and the custom selector (and it names your exporters based on their subtype):

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

Now your service simply receives an IMyExporterFactory and uses that to resolve the exporter:

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

You'll probably want to ensure that if the components are registered with lowercase names ("xml", "json") that your code always uses lowercase names (or use context.subtype.ToLower() in your ExporterComponentSelector).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文