My Current GeneralBindings : Ninject Module
public class GeneralBindings : NinjectModule
{
public override void Load()
{
// Requires Ninject.Extensions.Conventions
// This binds all interfaces to concretes of the same name eg IClass -> Class.
Kernel.Bind(x => x.FromAssembliesMatching("Company.Project.Scm*")
.SelectAllClasses()
.Excluding(typeof(AffectedCables),
typeof(ApplicationConfigurations),
typeof(ApplicationErrors),
typeof(ApplicationLogEvents),
typeof(AppUsers),
typeof(AppUsersContract),
typeof(Areas)
// etc..
)
.BindAllInterfaces());
then
Bind<IAffectedCables>().To<AffectedCables>()
.InSingletonScope()
.WithConstructorArgument("url", @"api/AffectedCables");
Bind<IApplicationErrors>().To<ApplicationErrors>()
.InSingletonScope()
.WithConstructorArgument("url", @"api/AppErrors");
Bind<IApplicationConfigurations>().To<ApplicationConfigurations>()
.InSingletonScope()
.WithConstructorArgument("url", @"api/AppConfigurations");
Bind<IApplicationLogEvents>().To<ApplicationLogEvents>()
.InSingletonScope()
.WithConstructorArgument("url", @"api/AppEventLogs");
Bind<IAppUsers>().To<AppUsers>()
.InSingletonScope()
.WithConstructorArgument("url", @"api/AppUsers");
Bind<IAppUsersContract>().To<AppUsersContract>()
.InSingletonScope()
.WithConstructorArgument("url", @"api/AppUserContract");
Bind<IAreas>().To<Areas>()
.InSingletonScope()
.WithConstructorArgument("url", @"api/Areas");
// Etc...
...
Can anyone suggest how to do this better? I'm sure that someone can create a single line of code that will save the copy and pasting that I have to perform at the moment.
A blind shot, not tested, but I would try with an attribute
public class AutoBindWithRouteAttribute : Attribute
{
public string Route { get; }
public AutoBindWithRouteAttribute(string route = null)
{
Route = route;
}
}
then
// to bind your first block of code for classes not featuring the attribute
kernel.Bind(
x => x.FromAssembliesMatching("").SelectAllClasses()
.Where(t => !t.GetCustomAttributes(typeof(AutoBindWithRouteAttribute), false).Any())
.BindAllInterfaces());
// to bind your second block of code for classes featuring the attribute
kernel.Bind(
x => x.FromAssembliesMatching("").SelectAllClasses()
.Where(t => t.GetCustomAttributes(typeof(AutoBindWithRouteAttribute), false).Any())
.BindWith(new BindingGenerator()));
where BindingGenerator
is :
public class BindingGenerator : IBindingGenerator
{
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
var att =
type.GetCustomAttributes(typeof(AutoBindWithRouteAttribute), false).FirstOrDefault() as
AutoBindWithRouteAttribute;
if (att == null) yield break;
yield return (IBindingWhenInNamedWithOrOnSyntax<object>)bindingRoot
.Bind(type.GetInterfaces().First())
.To(type)
.InSingletonScope()
.WithConstructorArgument("url", att.Route ?? $"api/{type.Name}");
}
}
usage would then be :
[AutoBindWithRoute()]
public class AffectedCables : IAffectedCables
[AutoBindWithRoute(@"api/AppErrors")]
public class ApplicationErrors : IApplicationErrors