Передача параметров в тип WCF ServiceHost с помощью Ninject 2 - PullRequest
3 голосов
/ 20 апреля 2011

Я хочу использовать расширение Ninject.Wcf для создания параметризованного экземпляра хоста службы.

Например, у меня есть класс MyWCFHandler с единственным следующим конструктором:

public MyWCFHandler(UserManager manager)
{
  _manager = manager;
}

Но когда я пишу var myServiceHost = new ServiceHost(typeof(MyWCFHandler));, у меня нет возможности передать объект зависимости конструктору.

Я не хочу связываться с пользовательским ServiceHost, подобным предложенному в Как передать значения вконструктор в моей службе wcf?

Я решил пойти по пути Ninject, но не в состоянии полностью понять, как действовать в моей ситуации.

Вот что я понимаю: расширение WCF в Ninject работает:

  1. Ссылка Ninject и Ninject.Extensions.WCF в моем проекте.
  2. Создание классакоторый наследует модуль Ninject и пишет что-то вроде:

    internal class ServiceModule : NinjectModule { public override void Load() { Bind<IUserManager>().To<UserManager>().WithConstructorParameters(myUserManagerIwantToUseInWCFHandler); } }

  3. Добавление ядра, инициализированного с новым ServiceModule (), в KernelContainer.

  4. Используйте NinjectServiceHost следующим образом:

    var service = KernelContainer.Kernel.Get<IMyWCFHandler>(); _host = new NinjectServiceHost( service );

И там мой хост должен быть готов к открытию.

Вопросы:

Как передать параметры моего конструктора в NinjectModule?Должен ли я создать экземпляр модуля NinjectModule, когда я буду готов связать с ним параметр?Как передать их в метод Get?

К сожалению, нет ни одного примера для простого показа параметризованного запуска ServiceHost.Меня даже не волнует, пользуюсь ли я этим Ninject.Какое бы решение ни показало хороший пример - я в порядке, поскольку я просто решаю, какой контейнер IoC использовать.

1 Ответ

6 голосов
/ 21 апреля 2011

По поводу нинъекта.Ответ зависит от того, хотите ли вы один сервис или новый экземпляр для каждого запроса.С услугой Singleton вы можете сделать следующее:

public class TimeServiceModule : NinjectModule
{
    /// <summary>
    /// Loads the module into the kernel.
    /// </summary>
    public override void Load()
    {
        this.Bind<ITimeService>().To<TimeService>();

        this.Bind<ServiceHost>().ToMethod(ctx => ctx.Kernel.Get<NinjectServiceHost>(new ConstructorArgument("singletonInstance", c => c.Kernel.Get<ITimeService>())));
    }
}

internal static class Program
{
    private static void Main()
    {
        var kernel = new StandardKernel(new TimeServiceModule());

        var serviceHost = kernel.Get<ServiceHost>();
        serviceHost.AddServiceEndpoint(typeof(ITimeService), new NetTcpBinding(), "net.tcp://localhost/TimeService");
        try
        {
            serviceHost.Open();
        }
        finally
        {
            serviceHost.Close();
        }
    }
}

По запросу:

public interface IServiceTypeProvider
{
    /// <summary>
    /// Gets the service types.
    /// </summary>
    /// <value>The service types.</value>
    IEnumerable<Type> Types { get; }
}

Func<Type, ServiceHost> serviceHostFactory

        foreach (Type serviceType in this.ServiceTypeProvider.Types)
        {
            // I do some magic here to query base contracts because all our service implement a marker interface. But you don't need this. But then you might need to extend the type provider interface.
            IEnumerable<Type> contracts = QueryBaseContracts(serviceType );

            var host = this.CreateHost(serviceType);

            foreach (Type contract in contracts)
            {
                Binding binding = this.CreateBinding();
                string address = this.CreateEndpointAddress(contract);

                this.AddServiceEndpoint(host, contract, binding, address);
            }

            host.Description.Behaviors.Add(new ServiceFacadeBehavior());

            this.OpenHost(host);

            this.serviceHosts.Add(host);
        }

    protected virtual ServiceHost CreateHost(Type serviceType )
    {
        return this.serviceHostFactory(serviceType );
    }

public class YourWcfModule : NinjectModule
{
    /// <summary>
    /// Loads the module into the kernel.
    /// </summary>
    public override void Load()
    {

        this.Bind<Func<Type, ServiceHost>>().ToMethod(
            ctx =>
            (serviceType) =>
            ctx.Kernel.Get<NinjectServiceHost>(new ConstructorArgument("serviceType", serviceType), new ConstructorArgument("baseAddresses", new Uri[] { })));
    }
}

Веселиться

...