【问题标题】:Possibilities of using abstract factories with StructureMap使用带有 StructureMap 的抽象工厂的可能性
【发布时间】:2012-04-26 09:03:52
【问题描述】:
public interface IExecuter
{
    void Execute();
}

public class Executer : IExecuter
{
    readonly Data _data;
    readonly IService _service;

    public Executer(Data data, IService service)
    {
        _data = data;
        _service = service;
    }

    public void Execute()
    {
        Console.WriteLine("I consume the data object with id {0}", _data.Id);
        _service.DoAnything();
    }
}

public interface IService
{
    void DoAnything();
}

public class Service : IService
{
    public void DoAnything()
    {
        Console.WriteLine("I do anything else");
    }
}

public class Data
{
    public int Id { get; set; }
    public string Description { get; set; }
}

现在我需要一个抽象工厂来创建 IExecuter,因为我需要将运行时值传递给构造函数。

可能性 #1 - 使用静态抽象工厂

public class FormularWindow
{
    public static Func<Data, IExecuter> CreateExecuter = data => {throw new NotImplementedException("");};

    public void InvokeExecuter()
    {
        var selectedData = GetSelectedData();
        var executer = CreateExecuter (selectedData);
        executer.Execute();
    }

    private static Data GetSelectedData()
    {
        return new Data { Id = 4, Description = "Test" };
    }
}

class Program
{
    static void Main()
    {
        ObjectFactory.Initialize(x =>
        {
            x.For<IExecuter>().Use<Executer>();
            x.For<IService>().Use<Service>();
        });
        FormularWindow.CreateExecuter = data => ObjectFactory.With(data.GetType(), data).GetInstance<IExecuter>();

        var consumer = ObjectFactory.GetInstance<FormularWindow>();

        consumer.InvokeExecuter();

        Console.ReadLine();
    }
}

可能性 #2 - 使用抽象工厂作为构造函数参数

public class FormularWindow
{
    readonly Func<Data, IExecuter> _createExecuter;

    public FormularWindow(Func<Data, IExecuter> createExecuter)
    {
        _createExecuter = createExecuter;
    }

    public void InvokeExecuter()
    {
        var selectedData = GetSelectedData();
        var executer = _createExecuter(selectedData);
        executer.Execute();
    }

    private static Data GetSelectedData()
    {
        return new Data { Id = 4, Description = "Test" };
    }
}

class Program
{
    static void Main()
    {
        ObjectFactory.Initialize(x =>
        {
            x.For<IExecuter>().Use<Executer>();
            x.For<IService>().Use<Service>();
            x.For<Func<Data, IExecuter>>().Use(data => ObjectFactory.With(data.GetType(), data).GetInstance<IExecuter>());
        });


        var consumer = ObjectFactory.GetInstance<FormularWindow>();

        consumer.InvokeExecuter();

        Console.ReadLine();
    }
}

可能性 #3 - 使用 IExecuterFactory

class Program
{
    static void Main()
    {
        ObjectFactory.Initialize(x =>
        {
            x.For<IExecuter>().Use<Executer>();
            x.For<IService>().Use<Service>();
            x.For<IExecuterFactory>().Use<ExecuterFactory>();
        });

        var consumer = ObjectFactory.GetInstance<FormularWindow>();

        consumer.InvokeExecuter();

        Console.ReadLine();
    }
}

public interface IExecuterFactory
{
    IExecuter Create(Data data);
}

public class ExecuterFactory : IExecuterFactory
{
    readonly IService _service;

    public ExecuterFactory(IService service)
    {
        _service = service;
    }

    public IExecuter Create(Data data)
    {
        return new Executer(data, _service);// ?!
    }
}


public class FormularWindow
{
    readonly IExecuterFactory _executerFactory;


    public FormularWindow(IExecuterFactory executerFactory)
    {
        _executerFactory = executerFactory;
    }

    public void InvokeExecuter()
    {
        var selectedData = GetSelectedData();
        var executer = _executerFactory.Create(selectedData);
        executer.Execute();
    }

    private static Data GetSelectedData()
    {
        return new Data { Id = 4, Description = "Test" };
    }
}

对于可能性 #3,我不知道如何实现它,如您所见。我可以再次在ExecuterFactory 的构造函数中使用Func,但这有点奇怪,因为我在抽象工厂 中使用了抽象工厂

还有 #4 的可能性来注入容器,但这不是一个好主意,因为引入了服务定位器

我问自己有没有办法在没有Func&lt;&gt;的情况下使用抽象工厂

【问题讨论】:

    标签: c# dependency-injection inversion-of-control structuremap abstract-factory


    【解决方案1】:

    我不会称它为 Abstract Factory,它看起来与某些人所说的简单工厂的功能等价。

    我建议你看看 Mark Seemann 的 post about abstract factories,他以简单的方式解释了几个选项。

    实际上,您可以在ExecuterFactory 中调用您的容器来解决您的依赖关系,以防它与您的组合根位于同一个项目中,或者您自己在您的手动编码工厂中new 将它们实例化。我更喜欢手动方法,因为我喜欢将容器的使用量保持在最低限度的想法。

    【讨论】:

    • 我编辑了我的问题。一个简单的工厂只允许创建一个具体的实现。抽象工厂返回类型是接口或抽象类形式的抽象。我的例子就是这种情况。
    • @Rookian 抱歉,我不想在这里开始讨论抽象工厂/简单工厂的定义,因为这不是重点。尽管如此,您似乎明白了我在说什么,并且您编辑了您的答案:) 它符合您的需求吗?
    • 我不确定更新执行器是否是个好主意。
    • @Rookian 好吧,你必须在运行时以某种方式实例化它,我认为在工厂中手动实例化某些东西并没有什么问题,毕竟它是一种模式。你不喜欢它的什么?
    猜你喜欢
    • 2011-03-29
    • 2017-02-08
    • 1970-01-01
    • 2011-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多