2

Let's assume that we have a service that needs to be initialized, but then it's a singleton. For example, something like this:

public interface IGraphsContainer
{
    void Initialize(IEnumerable<Graph> initialContent);

    void Add(Graph graph);

    bool Contains(Graph graph);

    IEnumerable<Graph> FindAll(Criteria complexCriteria);
}

Assume that the implemention has no dependencies. So it can be easily binded in a DI container and auto-injected into classes that need it.

This works for me, expect for the fact that I must not forget to initialize the container before using it. It needs some additional code to prevent this. That's why I am not enterily satisfied.

Is there a better solution for this that doesn't require the Initialize method?

EDIT: I was not clear about the singletion. The fact is, it's a singleton in its scope, which is NOT the application scope. Therefore this initialize method is invoked in some other AbstractFactory.

In this case, if Graphs are pulled from a folder and a user decides to change the folder, then we need to change the graphs based on that folder and thereby the initial containers content.

Here's the real example where I'm using this Initialize approach. The underlying algorithm is pretty complex and this is just a half of it. So far I need 3 things to be initialized like this.

6
  • 1
    You should really inject to the concrete and pass parameters down the stack until you hit something concrete and do the DI on construction. To initialize something the caller has to already know what it is (that includes factories), so it seems odd to have a function in an abstract interface for initialization when you should already have the information by the time that initialize can be called to initialize without the abstraction.
    – user204677
    Commented Nov 30, 2017 at 22:00
  • 1
    Oh I see, singleton -- argh. How many singletons do you have in your system that you feel the need to eliminate the requirement to call Initialize on them? The ideal solution is to avoid singletons, but if you insist, if you need to initialize these singletons and do the DI before they can be used, then just keep the singleton object references at null initially and just construct them with new SingletonType(initialContent) when you can meaningfully do so. Give the singletons a constructor which accepts the DI content as a parameter instead of relying on this Initialize method.
    – user204677
    Commented Nov 30, 2017 at 22:09
  • Thank you for your response. I edited my post. The singleton word was misleading.
    – Patrik Bak
    Commented Nov 30, 2017 at 22:24
  • How come the GeneratorFactory can't receive the generator input in its own constructor? If so, it could pass it along to the constructors of everything else it constructs there.
    – user204677
    Commented Dec 1, 2017 at 1:48
  • @DrunkCoder Because then it can't be easily binded via a DI container (NInject). At least I don't know how to do it. Now I simple bind IGeneratorFactory to GeneratorFactory
    – Patrik Bak
    Commented Dec 1, 2017 at 2:04

1 Answer 1

2

Is there a better solution for this that doesn't require the Initialize method?

I see two possible designs:

1.. initialContent should move to the constructor of the impl, and should be injected as a dependency. You should not make Initialize part of IGraphsContainer unless clients are expected to call it. Like so:

public interface IGraphsContainer
{
    void Add(Graph graph);
    bool Contains(Graph graph);
    IEnumerable<Graph> FindAll(Criteria complexCriteria);
}

public class DefaultGraphsContainer : IGraphsContainer
{
    public DefaultGraphsContainer(IEnumerable<Graph> initialContent)
    {
        // ...
    }
}

2.. If clients are expected to call Initialize, I would recommend extracting Initialize into its own interface as an abstract factory. You can then inject IGraphsContainerFactory or IGraphsContainer depending on whether the client should call Create (formerly Initialize) or not. Like so:

public interface IGraphsContainerFactory
{
    IGraphsContainer Create(IEnumerable<Graph> initialContent);
}

public interface IGraphsContainer
{
    void Add(Graph graph);
    bool Contains(Graph graph);
    IEnumerable<Graph> FindAll(Criteria complexCriteria);
}
1
  • Thank you for your response...I specified my problem. I think the first approach won't work. And regarding the second. That one seems fine, but I'm not sure how to do it with a DI container, that is initilized when the application starts. Specificly, is it possible to tell it it should return the last instance created by the factory? I'm using NInject.
    – Patrik Bak
    Commented Nov 30, 2017 at 22:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.