4
\$\begingroup\$

Consider this class:

using Ninject;
using Ninject.Syntax;
using Ninject.Parameters;

namespace MyApp.Dependencies.Factories
{
    public abstract class FactoryBase<T> where T : class
    {
        private IResolutionRoot _resolutionRoot;
        protected FactoryBase(IResolutionRoot resolutionRoot)
        {
            _resolutionRoot = resolutionRoot;
        }

        protected T Create(params IParameter[] parameters)
        {
            return _resolutionRoot.Get<T>(parameters);
        }
    }
}

What this class really abstracts away, is the _resolutionRoot.Get<T> part, allowing for concrete factory classes to look something like this:

//using Ninject; // not needed
using Ninject.Syntax;
using Ninject.Parameters;

public interface IUnicornFactory
{
    Unicorn Create(string name, int hornLength, Color color);
}

public class UnicornFactory : FactoryBase<Unicorn>, IUnicornFactory
{
    public UnicornFactory(IResolutionRoot resolutionRoot)
        : base(resolutionRoot)
    { }

    public Unicorn Create(string name, int hornLength, Color color)
    {
        return Create(new ConstructorArgument("name", name),
                      new ConstructorArgument("hornLength", hornLength),
                      new ConstructorArgument("color", color));
    }
}

Is this overkill, or something that I'll thank myself for later, when I have dozens of factory classes? I find the base factory merely allows for synctactic sugar in the concrete factory implementations - are there any side-effects to this?

\$\endgroup\$
4
  • \$\begingroup\$ Couldn't create a 'ninject' tag. Or does this question belong in StackOverflow? \$\endgroup\$ – Mathieu Guindon Apr 12 '13 at 15:17
  • \$\begingroup\$ I think it's covered by dependency-injection, but this is the right place to ask it. No experience with Ninject, so I can't answer, though. \$\endgroup\$ – Bobson Apr 12 '13 at 16:38
  • \$\begingroup\$ @Bobson: Ninject stuff tossed aside, the only thing I don't like is that the protected constructor is hiding the need for an IResolutionRoot in the concrete factory implementation - I believe ReSharper (R#) would help here but as far as "good design practices" are concerned is it ok for an abstract class to require a constructor argument that the concrete implementation can't quite know about until compilation fails with a "[base class] does not contain a constructor that takes 0 arguments" error? VS doesn't give a "Implement abstract class" shortcut for the constructor... \$\endgroup\$ – Mathieu Guindon Apr 12 '13 at 17:33
  • \$\begingroup\$ You can't require any specific form of the constructor be implemented, but by specifying any constructor on the abstract class, you require all children to call one of them, with all the appropriate arguments. The children can either hardcode those or take them in their own parameters and pass them on, but they have to supply them. \$\endgroup\$ – Bobson Apr 12 '13 at 17:43
3
\$\begingroup\$

Line-by-line I had exactly the same factory code. It smells, isn't it?

The correct solution would be to use Ninject Factory extension. I am happy since.

\$\endgroup\$
1
  • \$\begingroup\$ Sorry I took so long - the factory extension works nice, but for some weird reason I'm having issues with it when I use it with COM interop (see stackoverflow.com/questions/18395022/…), so for that specific project I'm discarding this idea, but in other .net projects it's indeed the perfect solution. \$\endgroup\$ – Mathieu Guindon Sep 7 '13 at 1:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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