实现WCF和Unity 的集成

Artech 已经写过一篇[原创]WCF后续之旅(7):通过WCF Extension实现和Enterprise Library Unity Container的集成,在这个解决方案中Unity的侵入性有点强,本文介绍一种具有更少的侵入性的解决方案。

第一步:创建一个自定义的InstanceProvider 来处理WCF服务。

InstanceProvider就是用于创建或者提供service instance的。除了提供service instance的创建者或者提供者的身份外,InstanceProvider还用于service instance的释放和回收。所有的IntanceProvider实现了System.ServiceModel.Dispatcher.IInstanceProvider 接口:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using Microsoft.Practices.Unity;
 using System.ServiceModel.Dispatcher;
 using System.ServiceModel;
 using System.ServiceModel.Channels; 
namespace Tencent.OA.Framework.ServiceModel
 {
     public class UnityInstanceProvider : IInstanceProvider
     { 
        public UnityContainer Container { set; get; }
         public Type ServiceType { set; get; } 
        public UnityInstanceProvider()
             : this(null)
         { 
        } 
        public UnityInstanceProvider(Type type)
         { 
            ServiceType = type;
             Container = new UnityContainer(); 
        } 
        #region IInstanceProvider Members 
        public object GetInstance(InstanceContext instanceContext, Message message)
         {
             return Container.Resolve(ServiceType);
         } 
        public object GetInstance(InstanceContext instanceContext)
         {
             return GetInstance(instanceContext, null);
         } 
        public void ReleaseInstance(InstanceContext instanceContext, object instance)
         { 
        } 
        #endregion 
    }
 } 

可以看到GetInstance方法用来获取服务实例,通过Unity的Resolve方法解析。

第二步:创建UnityInstanceProvider对应的Behavior

第一步已经创建了自定义的UnityInstanceProvider,现在需要在运行时插入我们这个新的Provider,这项工作可以通过IServiceProvider(定义一种检索服务对象的机制,服务对象是为其他对象提供自定义支持的对象)来完成。

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.ServiceModel.Dispatcher;
 using System.ServiceModel.Description;
 using System.ServiceModel;
 using System.Collections.ObjectModel;
 using System.ServiceModel.Channels;
 using Microsoft.Practices.Unity; 
namespace Tencent.OA.Framework.ServiceModel
 {
     public class UnityServiceBehavior : IServiceBehavior
     { 
        public UnityInstanceProvider InstanceProvider 
        { get; set; } 
        private ServiceHost serviceHost = null; 
        public UnityServiceBehavior()
         { 
            InstanceProvider = new UnityInstanceProvider(); 
        } 
        public UnityServiceBehavior(UnityContainer unity)
         {
             InstanceProvider = new UnityInstanceProvider();
             InstanceProvider.Container = unity; 
        } 
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
         { 
            foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
             { 
                ChannelDispatcher cd = cdb as ChannelDispatcher; 
                if (cd != null)
                 { 
                    foreach (EndpointDispatcher ed in cd.Endpoints)
                     {
                         InstanceProvider.ServiceType = serviceDescription.ServiceType;
                         ed.DispatchRuntime.InstanceProvider = InstanceProvider;
                     } 
                } 
            } 
        } 
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
         { } 
        public void AddBindingParameters(ServiceDescription serviceDescription,ServiceHostBase serviceHostBase,Collection<ServiceEndpoint> endpoints,
             BindingParameterCollection bindingParameters)
         { 
        } 
    } 
} 

当调用ApplyDispatchBehaviour,代码通过循环收集在我们的项目Endpoints,并传递给相应的服务类型的InstanceProvider。

第三步:创建自定义的增加新的Behavior的 Service Host

ServiceHost 提供了基本的“加载服务,配置endpoints,应用安全设置以及启动监听请求”机制。通过自定义一个ServiceHost将我们自己的Behavior添加进去。

using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.ServiceModel;
 using Microsoft.Practices.Unity; 
namespace Tencent.OA.Framework.ServiceModel
 {
     public class UnityServiceHost : ServiceHost
     { 
        public UnityContainer Container { set; get; } 
        public UnityServiceHost()
             : base()
         {
             Container = new UnityContainer();
         } 
        public UnityServiceHost(Type serviceType, params Uri[] baseAddresses)
             : base(serviceType, baseAddresses)
         { 
            Container = new UnityContainer(); 
        } 
        protected override void OnOpening()
         { 
            if (this.Description.Behaviors.Find<UnityServiceBehavior>() == null)
                 this.Description.Behaviors.Add(new UnityServiceBehavior(Container)); 
            base.OnOpening();
         } 
    } 
} 

当Service Host启动的时候,它就会检查我们的UnityServiceBehavior是否已经添加到Behaviors里面,如果没有就把它加入到Behaviors集合。

第四步:创建自定义的ServiceHostFactory

如果只是承载在Console Application、Windows Service或者其他非Web应用程序,我们的工作已经完成了。但在Web的.svc中,ServiceHost是动态创建的,没有显示的指定ServiceHost的Factory,那它在默认情况下是使用ServiceHostFactory的,而ServiceHostFactory产生的是ServiceHost对象,想要使用我们上一步中自定义的UnityServiceHost ,需要实现一个自定义的ServcieHostFactory,实现代码非常简单:

using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using Microsoft.Practices.Unity.Configuration;
 using Microsoft.Practices.Unity;
 using System.ServiceModel.Activation;
 using System.ServiceModel;
 using System.Configuration; 
namespace Tencent.OA.Framework.ServiceModel
 {
     public class UnityServiceHostFactory : ServiceHostFactory
     { 
        protected override ServiceHost CreateServiceHost( 
                                    Type serviceType, Uri[] baseAddresses)
         { 
            UnityServiceHost serviceHost = new UnityServiceHost(serviceType, baseAddresses);
             UnityContainer container = new UnityContainer();
             serviceHost.Container = container;
             //configure container 
             UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
             section.Containers.Default.Configure(serviceHost.Container);
             return serviceHost; 
        } 
    } 
} 

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏圣杰的专栏

Asp.net mvc 知多少(八)

本系列主要翻译自《ASP.NET MVC Interview Questions and Answers 》- By Shailendra Chauhan,想...

24590
来自专栏ASP.NET MVC5 后台权限管理系统

ASP.NET MVC5+EF6+EasyUI 后台管理系统(21)-权限管理系统-跑通整个系统

这一节我们来跑通整个系统,验证的流程,通过AOP切入方式,在访问方法之前,执行一个验证机制来判断是否有操作权限(如:增删改等) 原理:通过MVC自带筛选器,在筛...

78770
来自专栏大内老A

WCF技术剖析之五:利用ASP.NET兼容模式创建支持会话(Session)的WCF服务

在《基于IIS的WCF服务寄宿(Hosting)实现揭秘》中,我们谈到在采用基于IIS(或者说基于ASP.NET)的WCF服务寄宿中,具有两种截然不同的运行模式...

21190
来自专栏有趣的django

Django rest framework(7)----分页

第一种分页  PageNumberPagination 基本使用 (1)urls.py urlpatterns = [ re_path('(?P<ve...

66270
来自专栏大内老A

实践重于理论——创建一个监控程序探测WCF的并发处理机制

由于WCF的并发是针对某个封装了服务实例的InstanceContext而言的(参考《并发的本质》《并发中的同步》),所以在不同的实例上下文模式下,会表现出不同...

26480
来自专栏大内老A

我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案

几个星期之前写了一篇关于如何通过WCF进行 双向通信的文章([原创]我的WCF之旅(3):在WCF中实现双向通信(Bi-directional Communic...

18660
来自专栏cnblogs

Reactor模式的.net版本简单实现--DEMO

     近期在学习DotNetty,遇到不少的问题。由于dotnetty是次netty的.net版本的实现。导致在网上叙述dotnetty的原理,以及实现技巧...

41660
来自专栏大内老A

WCF版的PetShop之三:实现分布式的Membership和上下文传递

通过上一篇了解了模块内基本的层次划分之后,接下来我们来聊聊PetShop中一些基本基础功能的实现,以及一些设计、架构上的应用如何同WCF进行集成。本篇讨论两个问...

26750
来自专栏pangguoming

C# 简单日志文本输出

第一种  直接文件IO流写日志文件 using System.IO; public static void WriteLog(string strLog) { ...

36950
来自专栏技术博客

菜菜从零学习WCF九(会话、实例化和并发)

在服务协定上设置System.ServiceModel.ServiceContractAttribute.SessionMode值

11030

扫码关注云+社区

领取腾讯云代金券