Проблема службы WCF с использованием Ninject (перемещение из Виндзора) (InvalidOperationException) - PullRequest
2 голосов
/ 01 ноября 2010

Есть ли в доме эксперты Ninject? :) Недавно я пытался преобразовать мое приложение службы WCF и клиентское приложение Windows Forms из внедрения зависимости Castle Windsor в Ninject.

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

System.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 Wcf Extensions GitHub здесь кстати.

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

* Обновление * Я обнаружил, что не использую 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
}

1 Ответ

2 голосов
/ 01 ноября 2010

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

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");

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

-ian

...