Effective DI Registration Patterns in C#

cdependency-injectionninject

I've done this so many times but I never end up liking how my code turns out. I'm asking if anyone else has the same problems and can offer solutions or conventions that they've used to make cleaner code.

When I build a C# service, I get TopShelf, Log4Net, and Ninject all installed and set up. Inside of my service project, I end up with a class like this. The part I'm most interested in is SuperLargeStaticClassThing.RegisterDependencies(_kernel);

sealed class ServiceMain
{
    [NotNull]
    private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    private IKernel _kernel;

    /// <summary>   Starts the service.</summary>
    public void Start()
    {
        Log.Info("Service Start");

        // Step 1: Register Ninject Dependencies
        _kernel = new StandardKernel();
        SuperLargeStaticClassThing.RegisterDependencies(_kernel);

        // Step 2: Start Service Endpoints
        _kernel.Get<IEndpoint1>().Start();
        // ...
    }

    /// <summary>   Stops the service.</summary>
    public void Stop()
    {
        Log.Info("Service Stop");

        // Stop Service Endpoints
        _kernel.Get<IEndpoint1>().Stop();
        // ...
    }
}

And my SuperLargeStaticClassThing.RegisterDependencies(_kernel); method ends up being huge, ugly, monolithic, you name it. It's hundreds of lines of just binding interfaces to other types. Sometimes you can get away with convention based registration to make it shorter, but I feel like this isn't always a solution either. Not only is the method huge, it seems unwieldy. Sometimes certain dependencies need to be swapped out in chunks, so I'd enjoy seeing the different categories of dependencies registered together. I feel like there has to be a better way, but I'm stuck in finding one that I like.

Does anyone have any suggestions on a pattern to solve the problem of a huge and unwieldy registration method?

Best Answer

so I'd enjoy seeing the different categories of dependencies registered together.

Ninject provides the concept of a module to allow you to group related bindings into a single class.

https://github.com/ninject/Ninject/wiki/Modules-and-the-Kernel

class WeaponsModule : NinjectModule
{
    private readonly bool useMeleeWeapons;
    public WeaponsModule(bool useMeleeWeapons) {
        this.useMeleeWeapons = useMeleeWeapons;
    }

    public void Load()
    {
        if (this.useMeleeWeapons)
            Bind<IWeapon>().To<Sword>();
        else
            Bind<IWeapon>().To<Shuriken>();
    }
}

class Program
{
    public static void Main()
    {
        bool useMeleeWeapons = false;
        IKernel kernel = new StandardKernel(new WeaponsModule(useMeleeWeapons));
        Samurai warrior = kernel.Get<Samurai>();
        warrior.Attack("the evildoers");
    }
}
Related Topic