2010-11-01 5 views
2

Любые эксперты Ninject в доме? :) Я недавно пытался конвертировать мое приложение-приложение WCF и приложение для Windows Forms из приложения «Зависимость от зависмости Виндзора» от Ninject.Проблема с WCF-сервисом с использованием Ninject (переход от Windsor) (InvalidOperationException)

Все прошло отлично на стороне Win Forms, но я столкнулся с проблемами на стороне WCF. До сих пор я понял, что мне нужны расширения WCF для Ninject, чтобы использовать DI с WCF, который я сделал и ссылался, но все еще испытываю проблему, которую я считаю, когда моя услуга пытается решить:

Система .InvalidOperationException: тип WcfMemberService, предоставляемый в качестве значения атрибута Service в директиве ServiceHost или предоставленный в элементе конфигурации system.serviceModel/serviceHostingEnvironment/serviceActivations не удалось найти.

код у меня есть что то, что я думал, чтобы быть правильным, чтобы получить доступ только к примеру мой WcfMemberService выглядит следующим образом:

ServiceModule.cs:

public class ServiceModule : NinjectModule 
{ 
    private IKernel _parentContainer; 
    public ServiceModule(IKernel container) 
    { 
    this._parentContainer = container; 
    } 

    public override void Load() 
    { 
    Bind<IDataContextProvider>().To<DataContextProvider>() 
     .WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString); 
    Bind(typeof(IRepository<>)).To(typeof(Repository<>)); 
    Bind<IServiceLocator>().ToConstant(new NinjectServiceLocator(_parentContainer)); 
    Bind<IUserService>().To<UserService>(); 

    // ** WCF Services ** 
    Bind<Business.Common.Wcf.Services.Contracts.IMemberServiceContract>().To<Business.Common.Wcf.Services.MemberService>().InSingletonScope().Named("WcfMemberService"); 
    } 
} 

Предположение я сделал это при переходе от моей рабочей конфигурации Castle Windsor, то, что Named() должна быть той же записью, которая указана в объявлении вашего файла WCF .svc. Так что я сделал это следующим образом:

<%@ ServiceHost Language="C#" Service="WcfMemberService" Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" %> 

Довольно просто, я принял этот подход из примера решения TimeService, размещенное на странице Ninject ФОС Расширение GitHub here кстати.

Может ли кто-нибудь увидеть, что я сделал неправильно здесь, и почему «WcfMemberService» не будет разрешать? Он должен быть «WcfMemberService» в ядре и указан в объявлении @ServiceHost. Я не вижу, что еще может быть неправильным. Это точно так же, как я объявляю его в Castle Windsor, за исключением примерно разного синтаксиса, но оба используют Named() и оба указывают это имя в служебной части файла .svc.

* Update * Я обнаружил, если я не использую Named() подход, а просто установить мою службу в @ ServiceHost декларации, Business.Common.Wcf.Services.MemberService, Business.Common.Wcf.Services он работает. Но я все еще не понимаю, почему я не могу использовать Именованные службы. Благодарю.

Кстати, мой Ninject модуль загружается с помощью Global.asax.cs таким образом:

public class Global : NinjectWcfApplication 
{ 
    #region Overrides of NinjectWcfApplication 

    /// <summary> 
    /// Creates the kernel that will manage your application. 
    /// </summary> 
    /// <returns>The created kernel.</returns> 
    protected override IKernel CreateKernel() 
    { 
     // config to reside in executing directory 
     log4net.Config.XmlConfigurator.Configure(new FileInfo("log4net.config")); 
     var _container = new StandardKernel(); 
     _container.Load(new ServiceModule(_container)); 
     //_container.Load(new Log4netModule()); 
     ServiceLocator.SetLocatorProvider(() => _container.Get<IServiceLocator>()); 

     return _container; 
    } 

    #endregion 
} 
+0

Если @Ian Дэвис не собирается, вам лучше задать этот тип вещи в списке рассылки Ninject. –

+0

Спасибо Рубен, я попросил там и раньше, поэтому посмотрим, что получится :) – GONeale

ответ

2

.Named синтаксис (строка) используется в условной привязки.Например, если у вас есть

Bind<IService1>().To<MyService>().Named("MyServiceImpl"); 
Bind<IService1>().To<DefaultService(); 

Тогда DefaultService будет введен в качестве значения по умолчанию, если у вас есть что-то вроде следующего:

class MyForm([Named("MyServiceImpl")] IService1 service){...} 

или

kernel.Get<IService1>(metadata => metadata.Name == "MyServiceImpl"); 

или

kernel.Get<IService1>("MyServiceImpl"); 

Если у вас нет дефа ult для типа, и у вас есть только привязка условного имени, тогда при попытке создать экземпляр вы получите исключение активации.

-ian

+0

Спасибо за объяснение метода Named. Итак, лучший способ сделать это, ссылаясь на класс и сборку прямо в директиве '@ ServiceHost', как я уже сказал? и просто бежать с этим? – GONeale

+0

Похоже, что вы настроили все остальное правильно, поэтому ваши службы должны правильно вводить свои зависимости. Одна вещь, однако, вам не нужно предоставлять вашему модулю экземпляр ядра, поскольку он должен быть доступен как свойство при расширении NinjectModule. –