Нет ничего плохого в настройке привязок целых имен по имени, если это единственный способ достичь того, что вам нужно. IMO.
Итак, основной синтаксис:
Bind<IBusinessContext>().To<ConcreteBusinessContext>().Named("XYZ");
Или, если вам нужен определенный вызывающий класс для получения другой привязки, вы можете попробовать:
Bind<IIBusinessContext>().To<SomeOtherConcreteBusinessContext>().WhenInjectedInto<TypeOfCallingClass>();
Однако, если вызывающий класс (я говорю о классе, в котором есть IBusinessContextctor) предоставляет значение конфигурации, которое определяет, какой конкретный тип загружать, тогда вам нужно будет использовать делегат:
Bind<Func<string, IBusinessContext>>().ToMethod(ctx => str => DetermineWhichConcreteTypeToLoad(ctx, str));
//messy sudo code
static DetermineWhichConcreteTypeToLoad(IContext ctx, string str)
{
if(str == "somevalue"){
return ctx.Kernel.Get<ConcreteType1>();
else
return ctx.Kernel.Get<ConcreteType2>();
}
и ваш вызывающий класс будет выглядеть примерно так:
class DoStuff
{
Func<string, IBusinessContext>> contextFunc;
DoStuff(Func<string, IBusinessContext>> contextFunc)
{
this.contextFunc = contextFunc;
}
void SomeMethod()
{
var configuredValue = GetConfiguredValueSomehow();
var context = contextFunc(configuredValue); //<-- this passes your config value back to ninject in the ToMethod() lambda
//do something with context
}
}
В этом примере нет необходимости в именованных экземплярах, поскольку у вас есть метод, который загружает конкретный конкретный тип, однако вы все равно можете использовать именованные экземпляры, если хотите сделать что-то вроде этого:
Bind<IBusinessContext>().To<ConcreteBusinessContext>().Named("config1");
Bind<IBusinessContext>().To<SomeOtherBusinessContext>().Named("config2");
Bind<Func<string, IBusinessContext>>().ToMethod(ctx => str => ctx.Kernel.Get<IBusinessContext>().Named(str));
class DoStuff
{
Func<string, IBusinessContext>> contextFunc;
DoStuff(Func<string, IBusinessContext>> contextFunc)
{
this.contextFunc = contextFunc;
}
void SomeMethod()
{
var configuredValue = "config1";
var context = contextFunc(configuredValue); //<-- this will passthrough "config1" to the above ToMethod() method and ask for a IBusinessContext named "config1"
}
}
EDIT:Я забыл упомянуть, что если ваше значение конфигурации не должно исходить из вызывающего кода, то это делает вещи намного проще.Вместо этого ваш код может выглядеть примерно так:
// this method can just be a global method in you app somewhere
static string GetConfigValue()
{
//something like
return AppSetting.Get("config");
}
Bind<IBusinessContext>().To<ConcreteBusinessContext>().When(r => GetConfigValue() == "config1");
Bind<IBusinessContext>().To<SomeOtherBusinessContext>().When(r => GetConfigValue() == "config2");
class DoStuff
{
IBusinessContext context;
DoStuff(BusinessContext context)
{
this.context = context;
}
void SomeMethod()
{
//use the context value as you normally would
}
}
Вы можете быть креативными и вместо использования магических строк, ваш метод config может загрузить перечисление, а ваш метод When () может вместо этого проверить на равенство с перечислениемстроки, но вы поняли идею.Это известно как контекстное связывание в ninject, и я могу сказать вам, как когда-то заядлому пользователю SM, это гораздо более мощно, чем все, что было у SM.Изучите остальные методы When () и посмотрите, что вы можете сделать.