一个ServiceHost寄宿多个服务

WHY

Q: "啥? 一个ServiceHost只能寄宿一个ServiceType?? 那我有好多业务逻辑难道要我都塞到一个类里吗?"

A: 哦,你可以把业务逻辑抽像到多个Interface,然后用一个类来实现

Q: "那我的项目可能有多个人参与,每个人负责某一个模块,难道要我们N个人去维护一个cs类文件吗?"

A:你不知道有一个东西叫partial class吗?

Q:  "shit,你是说每回我要往服务端添加一些业务功能,都得重新编译一遍程序吗?"

A: 呃...这个...也许你可以...like this

http://www.cnblogs.com/levinknight/archive/2007/05/25/760176.html

and this

http://www.cnblogs.com/jillzhang/archive/2008/11/02/1325081.html

Q: “oh no, 这样我的系统还叫系统吗? 针对每个service一遍又一遍的权限验证和安全配置?”

A: >.<

WANT

1, 以插件的方式开发wcf服务端,业务模块以独立dll的方式注册到宿主里

2,业务模块的添加删除是动态的,服务端主程序无需重新编译

3,无须为每个业务模快servicetype单独做配置,注册一个业务模块只需在host里添加一个endpoint和操作契约

...

HOW

默认情况下,servicehost在收到客户端调用时,可以判断出调用的契约interface, 然后用构造函数传入的servicetype创建实例并转型为对应的interface进行方法调用

而为了实现一个servicehost能对应多个服务, 我们需要改变他的实例创建的行为,WCF里可以用InstanceProvider来实现这一机制.

具体InstanceProvider用法及wcf服务端的消息dispatch机制可以参考园子里的大牛Artech的《WCF后续之旅》系列文章:

http://www.cnblogs.com/artech/archive/2008/08/26/1276559.html

public class MyInstanceProvicer : IInstanceProvider
{
    private string contractType;
    public MyInstanceProvicer(string contractType)
    {
        this.contractType = contractType;
    }
    public object GetInstance(InstanceContext instanceContext,
        System.ServiceModel.Channels.Message message)
    {
        /*在注册业务模块的时候,可以把实现业务模块的assembly,业务模块的type name,
         * 业务模块所实现的契约接口记录到一张表里,然后在这里通过契约找到对应的业
         * 务模块信息,实例化出类实例,返回给servicehost*/
        switch (contractType)
        {
            case "IFoobar":
                return new WcfService1.Service1();
                break;
            case "ISayHello":
                return new WcfService2.Service1();
                break;
            default:
                return null;
                break;
        }
        return null;
    }
    public object GetInstance(InstanceContext instanceContext)
    {
        return GetInstance(instanceContext, null);
    }
    public void ReleaseInstance(InstanceContext instanceContext,
        object instance)
    {
        Console.WriteLine("releaseInstance::" + instance.ToString());
    }
}
public class InstanceProviderBehavior : IServiceBehavior
{
    void IServiceBehavior.AddBindingParameters(
        ServiceDescription serviceDescription,
        ServiceHostBase serviceHostBase,
        System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints,
        System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
    }
    void IServiceBehavior.ApplyDispatchBehavior(
        ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcher channelDispatcher
            in serviceHostBase.ChannelDispatchers)
        {
            foreach (EndpointDispatcher endpointDispatcher
                in channelDispatcher.Endpoints)
            {
                endpointDispatcher.DispatchRuntime.InstanceProvider =
                    new MyInstanceProvicer(endpointDispatcher.ContractName);
            }
        }
    }
    void IServiceBehavior.Validate(ServiceDescription serviceDescription,
        ServiceHostBase serviceHostBase)
    {
    }
}

通过ServiceBehavior把InstanceProvider应用到servicehost上

通过以上的方法,事实上我们已经拦截了servicehost对servicetype的实例化过程,可是我们还有一个问题得解决,这个servicehost本身应该怎么实例化呢?构造函数里的servicetype传什么??

由于servicehost在初始化的时候,会检查传入构造函数的serivcetype是否实现了在endpoint里注册的所有契约interface,只要有一个interface没实现就会抛出异常.

这可怎么办?我可不知道最后我的serivcehost会host多少个契约,这个servicetype是没办法在开发期间实现的.

幸好,dotnet提供了反射和动态创建类型的功能,在实例化servicehost的时候,把所有注册的业务模块契约接口列出来,并动态创建一个实现了这些接口的类型就可以了.

参考:

通过Emit实现动态类生成

http://www.souzz.net/html/edu/net/net11/3478.html

public class TypeCreator
{
    public TypeCreator()
    {
    }
    public Type build()
    {
        AppDomain currentAppDomain = AppDomain.CurrentDomain;
        AssemblyName assyName = new AssemblyName();
        assyName.Name = "DynamicAssemblyForServiceType";
        AssemblyBuilder assyBuilder =
            currentAppDomain.DefineDynamicAssembly(assyName,
            AssemblyBuilderAccess.Run);
        ModuleBuilder modBuilder =
            assyBuilder.DefineDynamicModule("DynamicModuleForServiceType");
        String newTypeName = "DynamicServiceType";
        TypeAttributes newTypeAttribute =
            TypeAttributes.Class | TypeAttributes.Public;
        //在这里把注册的业务模块契约列出来
        Type[] newTypeInterfaces = new Type[] {
            typeof(WcfService1.IFoobar), typeof(WcfService2.ISayHello) };
        TypeBuilder typeBuilder = modBuilder.DefineType(newTypeName,
            newTypeAttribute, null, newTypeInterfaces);
        //实现接口
        foreach (Type baseInterface in newTypeInterfaces)
        {
            MethodInfo[] targetMethods = baseInterface.GetMethods();
            foreach (MethodInfo targetMethod in targetMethods)
            {
                if (targetMethod.IsVirtual)
                {
                    ParameterInfo[] paramInfo = targetMethod.GetParameters();
                    Type[] paramType = new Type[paramInfo.Length];
                    for (int i = 0; i < paramInfo.Length; i++)
                        paramType[i] = paramInfo[i].ParameterType;
                    MethodBuilder methodBuilder = typeBuilder.DefineMethod(
                        targetMethod.Name,
                        MethodAttributes.Public | MethodAttributes.Virtual,
                        targetMethod.ReturnType, paramType);
                    ILGenerator ilGen = methodBuilder.GetILGenerator();
                    ilGen.Emit(OpCodes.Ret);   //该方法具体应该实现什么功能不重要.
                }
            }
        }
        return (typeBuilder.CreateType());
    }
}

现在有了servicetype,可以创建servicehost的实例了

ServiceHost host = new ServiceHost(new TypeCreator().build());
host.Description.Behaviors.Add(new InstanceProviderBehavior());
host.Open();

END

以上方法,基本实现了一个ServiceHost多个服务的功能,但是还没深入评估,园子里牛人多,希望能指出其中可能存在的陷阱、错误和不足, 拍谢!

posted on 2010-11-16 16:24 kingcomxu 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/sweethome/archive/2010/11/16/one_servicehost_mutil_service.html

一个ServiceHost寄宿多个服务相关推荐

  1. 从0设计一个基于Redis的锁服务

    作者:温灏,后端研发,专注于Python和Go,对分布式系统感兴趣,本文系作者投稿,有兴趣投稿的同学,请后台回复[投稿] 由于微服务大行其道,服务之间的协调工作变得越来越重要.今天来简单说一下如何搭建 ...

  2. 使用docker部署一个直接可用的puppet服务端

    思路: 在一个docker环境,直接拉下来笔者的镜像,直接启动一个可用的容器即可. 此镜像提供一个直接可用的 puppet服务端(foreman/activemq/mcollective-client ...

  3. 在 Docker 上运行一个 RESTful 风格的微服务

    tags: Microservice Restful Docker Author: Andy Ai Weibo: NinetyH GitHub: https://github.com/aiyanbo/ ...

  4. java服务器向客户端发消息_java一个简单的客户端向服务端发送消息

    java一个简单的客户端向服务端发送消息 客户端代码: package com.chenghu.tcpip; import java.io.IOException; import java.io.Ou ...

  5. 音频服务器未显示,Win7系统没有声音提示“一个或多个音频服务未运行”如何解决...

    在win7系统中没有声音,点击右下角小喇叭,按照提示进行修复完成后的"疑难解答已完成"界面,提示已找到问题"一个或多个音频服务未运行"如何解决呢?出现这样的情况 ...

  6. 一个简单的完成端口(服务端/客户端)类

    一个简单的完成端口(服务端/客户端)类 作者:spinoza 翻译:麦子芽儿, POWERCPP(后面部分内容) 下载源代码 原文网址:http://www.codeproject.com/KB/IP ...

  7. C#制作Windows service服务系列二:演示一个定期执行的windows服务及调试(windows service)(转载)...

    系列一: 制作一个可安装.可启动.可停止.可卸载的Windows service(downmoon原创) 系列二:演示一个定期执行的windows服务及调试(windows service)(down ...

  8. 利用SpringCloud搭建一个最简单的微服务框架

    利用SpringCloud搭建一个最简单的微服务框架 https://blog.csdn.net/caicongyang/article/details/52974406 1.微服务 微服务主要包含服 ...

  9. SmartSql使用教程(1)——初探,建立一个简单的CURD接口服务

    一.引言 最近SmartSql被正式引入到了NCC,借着这个契机写一个使用教程系列 二.SmartSql简介[摘自官方文档] 1. SmartSql是什么? SmartSql = MyBatis + ...

最新文章

  1. 一个Python小白5个小时爬虫经历
  2. 窥探当今AI芯片中的类脑模型
  3. MindCon | 杭京宁三大战场即将启动,火速来战!
  4. Centos7忘记密码——转
  5. VB案例:宁越电子琴
  6. wxPython多个窗口的基本结构
  7. 邓_phpcms_二次开发_留言板
  8. android wifi分析 实现原理,android framework wifi 开启原理
  9. java 随机生成不重复的数字_java中生成不重复随机的数字
  10. 齐兴皓 团队项目(任务五):项目回顾
  11. MSDC 4.3 接口规范(22)
  12. 实验2 运算器的编程实现
  13. Integer.valueOf、intValue、Integer.parseInt使用
  14. jQuery实现可编辑表格
  15. 由MAVEN入手浅谈项目构建与管理
  16. 明星热图|王嘉尔、刘诗诗代言新品牌;王一博、周笔畅、刘恺威出席活动;吴彦祖、黄晓明演绎品牌大片...
  17. (转)2008年精典骗术, 2009年你还会上当吗?
  18. 基于matlab的对称振子天线分析,基于Matlab的对称振子天线分析
  19. Java后端简历中的项目经验,斩获offer
  20. Electron理论知识 8 - 工具神器(Fiddle)

热门文章

  1. 【GNSS数据格式类】精密轨道SP3c与SP3d轨道格式说明
  2. 最好的婚姻:谈钱、说爱、聊性、话余生
  3. MAT500资产标签
  4. 怎样压缩pdf文件大小?pdf文件压缩方法
  5. 网件使用计算机mac地址吗,网件原生固件设置无线MAC地址过滤详细步骤
  6. scp远程拷贝文件出现permission denied
  7. 金山中等专业学校计算机,江苏省金山中等专业学校2021年招生简章
  8. 计算硬盘的计算机,[计算机组成原理]-磁盘容量计算,磁盘平均寻址时间计算和数据传输速率计算...
  9. 物联产品设计:让设备活起来的物联卡
  10. android梦网物联卡信息,摘自TechWeb:梦网物联云:实现智能穿戴只需一张物联网卡...