zoukankan      html  css  js  c++  java
  • 在WCF中使用Ninject轻量级IOC框架 之 SOAP风格服务

    在WCF中使用Ninject轻量级IOC框架 之 SOAP风格服务

    最近学习MVC 看到很多文章都用了Ninject框架进行解耦,就考虑是否能用在平时写的WCF服务中,因为毕竟目前还是总要写服务的……蛋疼ing……

    传送门:

    Ninject框架官网:

    http://www.ninject.org/download.html

    目前最新版本是3.0,另外需要下载WCF相关的扩展

    Ninject 入门:

    http://www.touchsunlight.com/coding/59.html

    WCF 入门:

    园子里找A大吧……

    以下为正文,请大家耐心围观,不要高呼No Picture&Code You Say a JB…… 最后会提供DEMO下载

    现在我们来看一个场景

    我想服务有一个行为,可以返回一段字符串,我们可以直接定义这个服务行为如下

    复制代码
    [ServiceContract]
    public class MessageService
    { 
          [OperationContract] 
           public string GetMessage() 
          {
               return "Hello World";
          }
    }
    复制代码

    但是这样不好,我不一定返回的就是Hello World这条消息,于是我们定义了一个接口,所有实现这个接口的类型都拥有返回消息的能力

    public interface IMessageProvider
    {
           string GetMessage();
    }
    public class DefaultMessageProvider:IMessageProvider
    {
         public string GetMessage(){return "Hello World";}
    }

    在服务里这么用

    复制代码
    [ServiceContract]
    public class MessageService
    {
          private IMessageProvider provider=null;
    
          public MessageService(IMessageProvider provider)
          {
                 this.provider=provider
          }
     
          [OperationContract] 
           public string GetMessage() 
          {
               return provider.GetMessage()
          }
    }
    复制代码

    我们的想法是美好的,但现实是残酷的,在对服务请求时,服务的实例,是由WCF管道创建的,我们无法手动new一个新的MessageService实例,也就代表我们无法通过构造函数向MessageService中注入IMessageProvider真正的实现类。

    这时候,我们就要利用Ninject通过查找关系映射列表,自动创建合理的依赖项实例这个特性了。

    这里简单介绍下Ninject框架的几个基本知识

    Ninject 内核Kernel 是整个Ninject框架的主入口点,也是关系列表的容器。

    我们可以通过IKernel kernel=new StandardKernel()来创建一个容器对象;

    Kernel通过Bind<T>.To<T>语法建立接口与实例间的关系,例如:kernel.Bind<IMessageProvider>().To<DefaultMessageProvider>();

    在建立接口与实现类之间的关系后,我们可以通过kenrel的Get<T>()方法来获取正确的对象实例,例如:IMessageProvider provider= kernel.Get<IMessageProvider>();

    这里我们获取到的对象实例为DefaultMessageProvider的实例。

    kernel对象在使用Get<T>()获取类型的实例时,会检查类型所有依赖项,并提供合理的值,我们看这个例子

    复制代码
    public Interface IA
    {
          void Todo();
    }
    
    public Interface IB
    {
          void Todo();
    }
    
    Public Class A:IA
    {
         public void Todo(){ // Todo}
    }
    
    public Class B:IB
    {
          private IA a;
          
          public B(IA a)
          {
                this a = a;
          }
    
         public void Todo()
      {
              a.Todo();
      }
    }
    
    
    public static Class Program
    {
             public static void Main()
              {
                      IKernel kernel=new StandardKernel();
                      kernel.Bind<IA>().To<A>();
                      kernel.Bind<IB>().To<B>();
                      
                      IB b=kernel.Get<IB>();
                      
                      b.Todo();
               }
    }
    复制代码

    在这个例子中IB的实现类,依赖于IA的实现,并且使用构造函数的方式进行了依赖注入。

    我们通过kernel.Get<IB>()时,会查找并创建B类型的实例,同时检查发现B类依赖于IA接口,NInject会继续检查关系列表中是否存在IA的映射,并创建合理的实例。

    最终返回B类型的实例,并且通过构造函数注入实现IA接口的类型的实例。

    现在,我们来看Ninject的一个扩展Ninject.Extensions.Wcf

    Ninject.Extensions.Wcf命名空间下提供了多种NinjectServiceHost以及他们的NinjectServiceHost<T>泛型版本。

    我们在创建宿主的时候,不需要手动的去new一个ServiceHost实例。

    可以直接通过kernel.Get<NinjectServiceHost<服务类型>>();的方式直接获取宿主。

    并且在服务宿主创建的时候,会自动检查所有依赖关系。

    示例代码:

    复制代码
    public static class Program
    {
              public static void Main()
             {
                      IKernel kernel=new StandardKernel();
                       
                      kernel.Bind<IMessageProvider>().To<DefaultMessageProvider>();
    
                      ServiceHost host=kernel.Get<NinjectServiceHost<MessageService>>();
                      
                      
              }
    }
    复制代码

    这样我们在创建服务宿主的时候,就会关联所有依赖了,也完美解决了之前遇到的问题。

    这里再次提醒,NinjectServiceHost<T>中的T为服务类型,而非契约类型,即使在关系映射列表中添加了kenrel.Bind<契约>().To<服务>();也不行。

    上边这个例子应用于自托管服务。

    还有一种服务的托管形式是IIS。

    寄宿于IIS中的服务,就更简单了。

    只需要改变下Global父类为NinjectHttpApplication 位于Ninject.Web.Common命名空间下,提供一个全局的Kernel即可。

    复制代码
    /// <summary>
        /// 这里要注意,实现NinjectHttpApplication
        /// </summary>
        public class Global : NinjectHttpApplication
        {
            protected override Ninject.IKernel CreateKernel()
            {
                //创建一个IOC容器,并且将服务管理模块与内部接口映射模块添加进去 
               
                return new StandardKernel(new ServiceModule(), new InternalModule());
    
                
            }
        }
    复制代码

    在服务的.svc页,需要声明Factory为NinjectServiceHostFactory,代码如下

    DemoService.svc

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

    扩展阅读:

    Ninject.Extensions.Wcf命名空间提供的扩展方法InRequestScope() 表示了产生的对象实例,生命周期为每次Request时创建,响应/运行完毕回收

    Ninject.Modules.NinjectModule 提供了依赖关系列表的模块化管理 

     结语:

      这篇文章不可否认很烂,其实也没什么好写的,很多东西扩展插件已经封装好了。

          但是在看老外的示例代码时出了很多莫名其妙的问题,因此自己重新写了一个DEMO,进行了整理和归纳。

          同时也希望为有兴趣在WCF中使用Ninject框架的朋友提供一份资料      

          心理明白……说不出来……一切尽在代码中吧

          附Demo下载:NinjectSOAP.rar

     
    标签: NinjectWcf
  • 相关阅读:
    设置文本框的 placeholder 的颜色
    CSS单行文字超出省略
    【持续跟新】剑指Offer_Java实现
    Android必修课-Activity生命周期
    如何查看Android的jks签名的MD5
    Flutter 文字边框/边框颜色
    Flutter initState 初始化调用 Provide报错
    flutter 系统通知栏Demo 基于flutter_local_notifications: ^1.4.1
    # Flutter学习笔记(一)
    一个技术人毕业到就业的思考
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2834419.html
Copyright © 2011-2022 走看看