• 实现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;

            }

        }

    }

    欢迎大家扫描下面二维码成为我的客户,为你服务和上云

  • 相关阅读:
    Karma: 3
    Karma:2. 集成 Karma 和 mocha 进行单元测试
    Android Eclipseproject开发中的常见调试问题(二)android.os.NetworkOnMainThreadException 异常的解决的方法
    CSDN日报20170226——《你离心想事成仅仅差一个计划》
    重装linuxserver简易流程
    移动端 h5开发相关内容总结——CSS篇
    Oracle学习笔记(6)——函数
    Spark学习
    Android教你怎样一步步打造通用适配器
    C语言学习
  • 原文地址:https://www.cnblogs.com/shanyou/p/1328047.html
Copyright © 2020-2023  润新知