Hooman Bahreini
Hooman Bahreini

Reputation: 15559

Defining Ninject's binding without scope to keep the code DRY

I have a Web project and a Windows Service project in my solution. I have created 2 different binding modules for these 2 projects, but as you can see it has a lot of duplicate code... the only difference is that I am using InRequestScope() for the Web project and InTransientScope() for Windows Service project.

Is it possible combine the bindings, and add the scope depending on the project/entry point?

public class WebModule : NinjectModule
{
    public override void Load()
    {
        Bind<ApplicationDbContext>().ToSelf().InRequestScope();
        Bind<IMyRepository>().To<MyRepository>().InRequestScope();
        // more types ... InRequetScope();
    }
}

public class ServiceModule : NinjectModule
{
    public override void Load()
    {
        Bind<ApplicationDbContext>().ToSelf().InTransientScope();
        Bind<IMyRepository>().To<MyRepository>().InTransientScope();
        // more types ... InTransientScope();
    }
}

Upvotes: 0

Views: 133

Answers (1)

Hooman Bahreini
Hooman Bahreini

Reputation: 15559

Update:

As explained by ninject team, we can use InRequestScope() in both scenarios... since there is no concept of Request in a Windows Service project, ninject would use the default scope, which is InTransientScope() in the service project.


Original Answer

The best solution that I have come up with is to create an extension method:

public static class NinjectExtensions
{
    public static IBindingNamedWithOrOnSyntax<T> GetScopeByName<T>(this IBindingInSyntax<T> syntax, string scope)
    {
        if (scope.Equals("request", StringComparison.InvariantCultureIgnoreCase))
        {
            return syntax.InRequestScope();
        }
        else if (scope.Equals("thread", StringComparison.InvariantCultureIgnoreCase))
        {
            return syntax.InThreadScope();
        }
        else if (scope.Equals("singleton", StringComparison.InvariantCultureIgnoreCase))
        {
            return syntax.InSingletonScope();
        }
        
        return syntax.InTransientScope();
    }
}

And set the scope dynamically.

public class MyModule : NinjectModule
{
    private string _scope = "transient";

    public MyModule()
    {
        if (Convert.ToBoolean(ConfigurationManager.AppSettings["IsWebProject"]))
        {
            _scope = "request";
        }
    }

    public override void Load()
    {
        Bind<ApplicationDbContext>().ToSelf().GetScopeByName(_scope);
        Bind<IMyRepository>().To<MyRepository>().GetScopeByName(_scope);
        // more types ... InRequetScope();
    }
}

Note: I am not sure if there is a better solution... this is just the cleanest approach that has come to my mind.

Upvotes: 1

Related Questions