Привязки на основе параметров в ninject 2.0 - PullRequest
3 голосов
/ 18 марта 2010

Я хочу использовать условное связывание в ninject, основываясь на переданных параметрах. У меня есть что-то вроде ниже:

public class Subject
{
}

public interface ITarget
{
}

public class Target1 : ITarget
{
}

public class Target2 : ITarget
{
}

А теперь мне нужно создать экземпляр интерфейса ITarget:

    public void MethodName(IKernel kernel)
    {
        ITarget target1 = kernel.Get<ITarget>(new Parameter("name", new Subject(), true)); // Should be instance of Target1
        ITarget target2 = kernel.Get<ITarget>(); // Should be instance of Target2
    }

У меня проблемы с определением правильных привязок. Я попробовал следующее:

kernel.Bind<ITarget>().To<Target1>().When(Predicate);
kernel.Bind<ITarget>().To<Target2>();

private bool Predicate(IRequest request)
{
    IParameter parameter = request.Parameters.Count == 0 ? null : request.Parameters[0];
    if (parameter == null)
    {
        return false;
    }
    object parameterValue = parameter.GetValue( /*what to put here?*/);
    return parameterValue != null && parameterValue.GetType().IsAssignableFrom(typeof(Subject));
}

но я не знаю, как получить значение переданного параметра. Мне нужно передать экземпляр IContext в метод GetValue, но я не знаю, как получить действительный экземпляр IContext. Или, может быть, есть лучший способ выполнить мою задачу?

EDIT: BindingMetadata - лучший способ решить мою проблему. Подробнее см. Контекстные привязки с Ninject 2.0

Привет

Ответы [ 2 ]

2 голосов
/ 18 марта 2010

Вам не достаточно IRequest.ParentContext? 1002 *

Кроме того, если все, что вам нужно, это использовать имя для устранения неоднозначности нескольких экземпляров [и вы будете в состоянии предоставлять его каждый раз и будете рады работать в таком явном порядке расположения службы вместо использования DI в качестве IDeity намерен], то есть перегрузка Get с именем и WithName для на стороне Bind.

РЕДАКТИРОВАТЬ: провел некоторое время в отражателе, но я все еще не намного мудрее. Механизм параметров, по-видимому, предназначен для переопределения определенных значений в контексте фактического связывания, а не как часть выбора связующего, который применяется. Установление контекста выполняется только в одном месте внутри (хотя Context имеет публичный ctor), поэтому не похоже, что для этого есть изящная фабрика.

Соответствует ли ваш реальный сценарий механизму ограничений (из которых использование имени для фильтрации является просто самым простым случаем). то есть, вы можете выразить Get как-то так:

_kernel.Get<ITarget>( (Ninject.Planning.Bindings.BindingMetadata metadata)=>metadata.Has("x") );

Надеюсь @ Ян Дэвис скоро придет, так как я бы тоже хотел узнать ответ: D

1 голос
/ 20 марта 2010

IIRC запрос может быть частью нескольких контекстов.Параметры, которые вы видите, являются только параметрами, указанными в вызове Get.В приведенном вами примере вы должны иметь возможность передать значение null как IContext, чтобы получить экземпляр вашего объекта.Поскольку вы предоставляете объект вместо обратного вызова, параметр создает обратный вызов как ctx => value ->, таким образом, обратный вызов не использует предоставленное вами значение контекста.

...