将Ninject WCF扩展与WCF Web服务一起使用

将Ninject WCF扩展与WCF Web服务一起使用,wcf,dependency-injection,ninject,Wcf,Dependency Injection,Ninject,我有一个WCF web服务,我想在其中使用我的存储库和服务,我希望将这些存储库和服务依赖注入到我的WCF web服务中,但是Ninject WCF扩展示例几乎有一个ctor,它正在实例化每个依赖项的一个实例,我不想要,我想要一个更纯粹的依赖项注入 如果有人成功地将Ninject与WCF结合使用,谷歌似乎不会返回与我正在寻找的主题相关的结果 的隐藏代码有: 这些构造函数混淆了这个问题——Ninject将选择最具体的构造函数。该示例的一般问题是它涵盖了所有基础(IIS托管、EXE托管、服务托管)

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

如果有人成功地将Ninject与WCF结合使用,谷歌似乎不会返回与我正在寻找的主题相关的结果

的隐藏代码有:



这些构造函数混淆了这个问题——Ninject将选择最具体的构造函数。该示例的一般问题是它涵盖了所有基础(IIS托管、EXE托管、服务托管),而WCF也不能使所有这些内容都易于管理(@Ian Davis:我很可能是错的,你能提供一些更详细的信息吗?也许是以自述文件中示例说明的摘要的形式,也许是以使用BI的各种情况的原因的更详细的形式?

我目前在我的WCF中使用Ninject(v3)的方式是基于Ninject WCF扩展和

简而言之,我正在做的是:

1) 通过NuGet,我在我的Wcf项目中添加了对Ninject.Extensions.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;
    }
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上下文在请求期间保持不变

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
    }
}
    <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>
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)
    {
    }
}
}
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();
        }
    }
}
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)
        {
        }
    }
}