Question

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

Now I need an abstract factory to create the IExecuter, because I need to pass a run-time value into the constructor.

Possibility #1 - use a static abstract factory:

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

Possibility #2 - use an abstract factory as a constructor parameter:

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

Possibility #3 - Use a 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" };
    }
}

With possibility #3 I do not know how to implement it as you can see. I could again use Func in the constructor of the ExecuterFactory, but that would be a kind of strange, because I use an abstract factory inside an abstract factory.

There would be also a #4 possibility to inject the container, but that would be not a good idea, because of introducing a service locator.

I ask myself if there is a way of using abstract factories without Func<>?

Was it helpful?

Solution

I wouldn't call that an Abstract Factory, it looks like the functional equivalent of what some call a Simple Factory.

I suggest you to have a look at Mark Seemann's post about abstract factories, he explains several options in a simple manner.

Practically, you could call your container in ExecuterFactory to solve your dependencies in case it resides in the same project as your composition root or instantiate them yourself newing them in your manually coded factory. I prefer the manual approach, because I like the idea of keeping the usage of the container at a minimum.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top