将 Ninject WCF 扩展与 WCF Web 服务结合使用

发布于 2024-09-14 00:59:57 字数 190 浏览 3 评论 0原文

我有一个 WCF Web 服务,我想在其中使用我的存储库和服务,我希望将其依赖项注入到我的 WCF Web 服务中,但是 Ninject WCF 扩展示例几乎有一个 ctor 正在实例化每个依赖项的实例,我不想要,我想要更纯粹的依赖注入。

有没有人成功地将 Ninject 与 WCF 结合使用,Google 似乎没有返回我正在寻找的主题的相关结果。

I have a WCF web service in which I want to use my Repositories and Services which I wish to dependency inject into my WCF web service, however the Ninject WCF Extension example pretty much has a ctor which is instantiating an instance of each dependency, which I don't want, I wanted a purer dependency injection.

Has anyone had any success with using Ninject with WCF, Google seems to return little relevant results for the topics I am looking for.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

病毒体 2024-09-21 00:59:57

TimeService< 背后的代码/a> 有:

<%@ ServiceHost Language="C#" Debug="true" Service="WcfTimeService.TimeService" CodeBehind="TimeService.svc.cs" **Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"** %>

混蛋注入 演员混淆了事情 - Ninject将选择最具体的构造函数。该示例的一般问题是它涵盖了所有基础(IIS 托管、EXE 托管、服务托管),并且 WCF 并不完全使所有这些东西易于管理(@Ian Davis:我很容易错,你能提供请提供更多详细信息,也许是以自述文件中示例说明的摘要的形式,也许还可以更详细地说明您使用 BI 的各种情况的原因?)

The code behind for TimeService has:

<%@ ServiceHost Language="C#" Debug="true" Service="WcfTimeService.TimeService" CodeBehind="TimeService.svc.cs" **Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"** %>

The bastard injection ctors confuse the matter - Ninject will choose the most specific constructor. The general problem with the sample is that it's covering all the bases (IIS Hosted, EXE hosted, Service Hosted), and WCF doesnt exactly make all this stuff easy to manage either (@Ian Davis: I could easily be wrong, can you provide some more detail please , perhaps in the form of a summary of what the samples illustrate in the README, and perhaps more detail in the why of the various cases where you've used BI?)

猥︴琐丶欲为 2024-09-21 00:59:57

我目前在 WCF 中使用 Ninject (v3) 的方式基于 Ninject WCF 扩展和 Pieter De Rycke 的精彩博客文章

简而言之,这就是我正在做的事情:

1)通过 NuGet,我已将 Ninject.Extensions.Wcf 的引用添加到我的 WCF 项目中。这将创建带有 NinjectWebCommon.cs 的 App_Start 文件夹,该文件夹负责初始化 Ninject。

2) 通常,您可以在 NinjectWebCommon.cs 的 CreateKernel 方法中设置 Ninject 映射。但是,由于我在同一解决方案中有一个 MVC3 站点,并且希望该站点具有相同的 Ninject 映射,因此我的 CreateKernel 如下所示:

    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        InfrastructureSetup.RegisterServices(kernel);
        return kernel;
    }

3) 在 InfrastructureSetup.RegisterServices 中,我有我的 Ninject 映射:

public static class InfrastructureSetup
{
    public static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IRepositoryContext>().To<MyEntityFrameworkContext>().InRequestScope();
        kernel.Bind<IFooRepository>().To<FooRepository>().InRequestScope();
        kernel.Bind<IBarRepository>().To<BarRepository>().InRequestScope();

        // ... and so on. I want InRequestScope() for the EF context, since
        // otherwise my repositories (which take IRepositoryContext in their 
        // constructors) end up getting different EF contexts, messing things up
    }
}

4) 我还想注入东西( IFooService 等)到我的 WCF 构造函数,因此我根据 Pieter De Rycke 的建议编辑了 WCF 项目的 Web.config:

    <behaviors>
        <serviceBehaviors>
            <behavior name="">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="false" />
                <!-- Add the Ninject behavior to the WCF service. This is needed to support dependency injection to the WCF constructors -->
                <ninject />
            </behavior>
        </serviceBehaviors>
    </behaviors>
  <extensions>
    <behaviorExtensions>
      <!-- Add the Ninject behavior extension -->
      <add name="ninject"
        type="MyWCFProject.Infrastructure.NinjectBehaviorExtensionElement, MyWCFProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </behaviorExtensions>
  </extensions>

5)在 MyWCFProject.Infrastruct 命名空间中,我有三个文件,它们基本上是从Pieter:

NinjectBehaviorAttribute.cs:

using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using Ninject.Web.Common;

namespace MyWCFProject.Infrastructure
{
public class NinjectBehaviorAttribute : Attribute, IServiceBehavior
{
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
        Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {   
        Type serviceType = serviceDescription.ServiceType;

        // Set up Ninject to support injecting to WCF constructors
        var kernel = new Bootstrapper().Kernel;
        IInstanceProvider instanceProvider = new NinjectInstanceProvider(kernel, serviceType);

        foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
        {
            foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)
            {
                DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
                dispatchRuntime.InstanceProvider = instanceProvider;
            }
        }
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }
}
}

NinjectBehaviorExtensionElement.cs:

using System;
using System.ServiceModel.Configuration;

namespace MyWCFProject.Infrastructure
{
    public class NinjectBehaviorExtensionElement : BehaviorExtensionElement
    {
        public override Type BehaviorType
        {
            get { return typeof(NinjectBehaviorAttribute); }
        }

        protected override object CreateBehavior()
        {
            return new NinjectBehaviorAttribute();
        }
    }
}

NinjectInstanceProvider.cs:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using Ninject;

namespace MyWCFProject.Infrastructure
{
    public class NinjectInstanceProvider : IInstanceProvider
    {
        private Type serviceType;
        private IKernel kernel;

        public NinjectInstanceProvider(IKernel kernel, Type serviceType)
        {
            this.kernel = kernel;
            this.serviceType = serviceType;
        }

        public object GetInstance(InstanceContext instanceContext)
        {
            return this.GetInstance(instanceContext, null);
        }

        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            return kernel.Get(this.serviceType);
        }

        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
        }
    }
}

目前,这个解决方案似乎运行良好;依赖项注入适用于 WCF 和 MVC3 站点,我可以请求将依赖项注入到 WCF 构造函数中,并且 EF 上下文在请求期间保持不变。

The way I am currently using Ninject (v3) with my WCF is based on the Ninject WCF extension and Pieter De Rycke's great blog post.

In a nutshell, here's what I'm doing:

1) Via NuGet, I've added a reference to Ninject.Extensions.Wcf into my WCF project. This creates the App_Start folder with NinjectWebCommon.cs, which takes care of initializing Ninject.

2) Typically, you'd set up your Ninject mappings in the CreateKernel method in NinjectWebCommon.cs. However, since I have a MVC3 site in the same solution and want the same Ninject mappings for that site, my CreateKernel looks like this:

    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        InfrastructureSetup.RegisterServices(kernel);
        return kernel;
    }

3) In InfrastructureSetup.RegisterServices, I have my Ninject mappings:

public static class InfrastructureSetup
{
    public static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IRepositoryContext>().To<MyEntityFrameworkContext>().InRequestScope();
        kernel.Bind<IFooRepository>().To<FooRepository>().InRequestScope();
        kernel.Bind<IBarRepository>().To<BarRepository>().InRequestScope();

        // ... and so on. I want InRequestScope() for the EF context, since
        // otherwise my repositories (which take IRepositoryContext in their 
        // constructors) end up getting different EF contexts, messing things up
    }
}

4) I want to also inject stuff (IFooService etc.) to my WCF constructors, so I've edited the Web.config for the WCF project with the advice from Pieter De Rycke:

    <behaviors>
        <serviceBehaviors>
            <behavior name="">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="false" />
                <!-- Add the Ninject behavior to the WCF service. This is needed to support dependency injection to the WCF constructors -->
                <ninject />
            </behavior>
        </serviceBehaviors>
    </behaviors>
  <extensions>
    <behaviorExtensions>
      <!-- Add the Ninject behavior extension -->
      <add name="ninject"
        type="MyWCFProject.Infrastructure.NinjectBehaviorExtensionElement, MyWCFProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </behaviorExtensions>
  </extensions>

5) In the MyWCFProject.Infrastructure namespace, I have three files which are basically copy-paste from Pieter:

NinjectBehaviorAttribute.cs:

using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using Ninject.Web.Common;

namespace MyWCFProject.Infrastructure
{
public class NinjectBehaviorAttribute : Attribute, IServiceBehavior
{
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
        Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {   
        Type serviceType = serviceDescription.ServiceType;

        // Set up Ninject to support injecting to WCF constructors
        var kernel = new Bootstrapper().Kernel;
        IInstanceProvider instanceProvider = new NinjectInstanceProvider(kernel, serviceType);

        foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
        {
            foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)
            {
                DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
                dispatchRuntime.InstanceProvider = instanceProvider;
            }
        }
    }

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }
}
}

NinjectBehaviorExtensionElement.cs:

using System;
using System.ServiceModel.Configuration;

namespace MyWCFProject.Infrastructure
{
    public class NinjectBehaviorExtensionElement : BehaviorExtensionElement
    {
        public override Type BehaviorType
        {
            get { return typeof(NinjectBehaviorAttribute); }
        }

        protected override object CreateBehavior()
        {
            return new NinjectBehaviorAttribute();
        }
    }
}

NinjectInstanceProvider.cs:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using Ninject;

namespace MyWCFProject.Infrastructure
{
    public class NinjectInstanceProvider : IInstanceProvider
    {
        private Type serviceType;
        private IKernel kernel;

        public NinjectInstanceProvider(IKernel kernel, Type serviceType)
        {
            this.kernel = kernel;
            this.serviceType = serviceType;
        }

        public object GetInstance(InstanceContext instanceContext)
        {
            return this.GetInstance(instanceContext, null);
        }

        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            return kernel.Get(this.serviceType);
        }

        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
        }
    }
}

At the moment, this solution seems to be working well; dependency injection is working for both the WCF and the MVC3 site, I can request dependencies to be injected to the WCF constructors and the EF context stays around for the duration of the request.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文