Как я могу заставить Ninject 2 использовать конструктор без параметров для LINQ to SQL DataContext? - PullRequest
11 голосов
/ 21 июля 2009

Я начал использовать Ninject 2 (скачанный вчера с Github, включая проект расширения MVC) с проектом, основанным на следующих технологиях:

  • .Net 3.5 Sp1
  • ASP.NET MVC 1.0
  • LINQ to SQL

Ничего волшебного здесь - у меня есть несколько интерфейсов репозитория (названных как IEntityRepository), которые реализованы с использованием LINQ to SQL в коде времени выполнения (и с использованием хеш-таблицы в коде модульного теста). Каждому из этих репозиториев необходим экземпляр DataContext из LINQ to SQL для связи с базой данных, так что это параметр конструктора в конкретных классах репозитория. Привязка настроена так:

Kernel.Bind<MyDataContext>().ToSelf().InRequestScope();

Причина этого в том, что я хочу иметь возможность обмениваться сущностями между различными репозиториями, если мне понадобится больше их, и с философией работы LINQ to SQL datacontext мне кажется, что имеет смысл создать по одному на HttpRequest.

Обычно я использую конструктор без параметров для MyDataContext - я не рассматриваю это как риск, поскольку он используется для внутреннего проекта в тестовой системе, поэтому «встроенная» строка соединения в текстовом тексте данных безвредна. Однако, поскольку Ninject 2 является «жадным» и требует конструктора с параметрами MOST, и я не могу реально вставить параметр [Inject] в сгенерированный код каким-либо значимым образом, я получаю сообщение об ошибке всякий раз, когда Ninject пытается создать один из моих контроллеры (для которых требуется репозиторий, для которого требуется текст данных).

Я видел упоминание IConstructorScorer и возможность сделать «инвертированный», который бы всегда использовал конструктор с параметрами LEAST, но опять же, это изменило бы, как инъекция работает для всего остального - поведение по умолчанию вероятно, что я хочу для всего, кроме datacontext.

Итак, есть ли хороший, чистый способ указать, что эта привязка (и только эта привязка) должна использовать определенный конструктор? Можем ли мы сделать то же самое с провайдерами, как в Ninject 1, и, возможно, поставить нашу собственную «фабрику»? Или я должен просто сдаться и попытаться ввести параметры в текстовый текст, который имеет смысл?

Ответы [ 2 ]

7 голосов
/ 02 мая 2010

Полагаю, вы могли бы также использовать привязку ToMethod, чтобы избежать реализации собственного провайдера, вот как я это использую:

Kernel.Bind<MyDataConext>().ToMethod(c => new MyDataContext())
6 голосов
/ 22 июля 2009

Разобрался - это довольно легко сделать, связавшись с провайдером;

Kernel.Bind<MyDataContext>().ToProvider<ContextProvider>().InRequestScope();

Теперь Ninject будет вызывать мой ContextProvider всякий раз, когда ему нужно построить один из этих надоедливых объектов DataContext. Вот как выглядит мой класс провайдера:

public class ContextProvider : IProvider
{
    #region IProvider Members

    public object Create(IContext context)
    {
        return new MyDataContext();
    }

    public Type Type
    {
        get { throw new NotImplementedException(); }
    }

    #endregion
}

Похоже, мне это сошло с рук - работает нормально. :)

...