Внедрение зависимостей в службы MVC3 WCF с использованием расширений Ninject

#wcf #asp.net-mvc-3 #ninject-extensions

#wcf #asp.net-mvc-3 #ninject-extensions

Вопрос:

У меня есть приложение MVC3, которое должно предоставлять некоторые функции через WCF. Некоторые из этих функций имеют зависимости, и я хотел бы внедрить их с помощью Ninject, но я, должно быть, упускаю что-то очевидное здесь, поскольку это не работает. Кто-нибудь может дать подсказку? Вот что я сделал:

1) в моем приложении MVC3 я добавляю расширения Ninject Wcf через nuget.

2) Я добавляю .svc файл, подобный:

 <%@ ServiceHost Service="MyWeb.LookupService" 
  Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"%>
  

3) Я добавляю соответствующий код, подобный (это просто тест, поэтому я использую фиктивный интерфейс прямо здесь):

 [ServiceContract]
public interface ILookupService
{
    [OperationContract]
    int GetProjectIdByCode(string sCode);
}

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class LookupService : ILookupService
{
  private readonly ISomeRepository _repository;
  public LookupService(ISomeRepository repository)
  {
    _repository = repository;
  }

  public int GetProjectIdByCode(string sCode)
  {
    //... use _repository
  }
}
  

4) в App_Start /NinjectMVC3.cs:

 private static void RegisterServices(IKernel kernel)
{
    string sConnection = ConfigurationManager.ConnectionStrings["SomeEntities"].ConnectionString;
    // WCF
    kernel.Bind<ServiceHost>().To<NinjectServiceHost>();

    kernel.Bind<ISomeRepository>()
        .To<AConcreteRepository>()
        .WithConstructorArgument("sConnection", sConnection);
}
  

Теперь, когда я обращаюсь к svc, я получаю следующее исключение из Ninject:

Система.Исключение ArgumentNullException не было обработано пользовательским кодом
Message=Cannot be null Имя параметра: корневой источник =Ninject
имя_параметра=root StackTrace: в Ninject.Инфраструктура.Убедитесь.ArgumentNotNull (аргумент объекта, имя строки) в c:ProjectsNinjectMaintenance2.2ninjectsrcNinjectInfrastructureEnsure.cs:line 20 в расширениях Ninject.ResolutionExtensions.GetResolutionIterator (корневой каталог IResolutionRoot, служба типов, параметры функции 2 constraint, IEnumerable 1, логическое значение IsOptional, логическое значение isUnique) в c:ProjectsNinjectMaintenance2 .2ninjectsrc NinjectSyntaxResolutionExtensions.cs: строка 258 в Ninject.ResolutionExtensions.Получаем[T] (корень IResolutionRoot, параметры IParameter[]) в c:ProjectsNinjectMaintenance2.2ninjectsrcNinjectSyntaxResolutionExtensions.cs:line 37 в Ninject.Extensions.Wcf.NinjectServiceHostFactory.Создайте ServiceHost (тип ServiceType, базовые адреса Uri[]) в c:ProjectsNinjectMaintenance2.2ninject.extensions.wcfsrcNinject.Extensions .Wcf NinjectServiceHostFactory.cs: строка 48 в системе.ServiceModel.Активация.ServiceHostFactory.Создайте ServiceHost(String constructorString, базовые адреса Uri[]) в системе.ServiceModel.Среда serviceHostingEnvironment.HostingManager.Создайте службу (String normalizedVirtualPath) в системе.ServiceModel.Среда serviceHostingEnvironment.HostingManager.ActivateService(String normalizedVirtualPath) в системе.ServiceModel.Среда serviceHostingEnvironment.HostingManager.Обеспечение доступности службы (String normalizedVirtualPath)

Комментарии:

1. Есть ли причина, по которой вы используете Ninject, а не Castle Windsor? Не то чтобы это плохой выбор или что-то в этом роде, но есть довольно хорошие руководства по подключению Windsor к MVC3

2. Спасибо, я использую Ninject, потому что это выбор команды, по сути, потому, что его можно использовать в проектах wpf, silverlight и wp7. Я мог бы предложить другие фреймворки, только если они соответствуют хотя бы этим спецификациям (и в любом случае я должен каким-то образом доказать, что это было бы лучше, чем NJ для наших целей… Я никогда этим не пользовался, но я открыт для предложений :).

Ответ №1:

Можете ли вы попробовать добавить защищенный конструктор без параметров в свой класс реализации.

Полагаю, servicehost также нуждается в конструкторе без параметров.

Я взглянул на фабрику хостов службы Ninject и на предоставленную вами трассировку стека. Похоже, что это сбой при выполнении следующих проверок:

       Ensure.ArgumentNotNull((object) root, "root");
      Ensure.ArgumentNotNull((object) service, "service");
      Ensure.ArgumentNotNull((object) parameters, "parameters");
  

Убедитесь, что вы передаете все требуемые параметры при использовании NinjectServiceHostFactory. Стоит попробовать изменить порядок регистрации.

Также перейдите по следующей ссылке здесь, которая объясняет, как использовать Ninject для размещения службы wcf.

Комментарии:

1. Не уверен, понял ли я, что вы имели в виду, но в моем классе реализации уже есть общедоступный ctor без параметров по умолчанию, использующий строку подключения по умолчанию. Однако «Производственный» будет использоваться через другой конструктор со строковым параметром, поэтому мне нужен мой DI, чтобы передать ему эту строку. В любом случае, я продолжаю получать эту ошибку даже с обоими ctor.

2. Я думал, что NInject будет использовать конструктор без параметров на сервере для загрузки. Можете ли вы заглянуть в NInjectServiceHostFactory о том, как он размещает службу WCF. Наверняка это как-то связано с NInject. Вы можете использовать dotpeek, чтобы увидеть реализацию NInjectServiceHostFactory.

3. Я просмотрел код в Ninject и, похоже, он не работает, потому что не удается передать какой-то параметр.