• WCF服务器搭建服务Host篇(ServiceHostGroup实现host) wu


    研究WCF也有一段时间了,开始研究是因为对remoting的一个应用,然后开始了WCF的学习历程,对于Hello World的Demo这里就不记载啦,当我摸索了一段时间之后,发现一个问题一直在困扰着我,就是众所周知可以通过ServiceHost来host一个个的WCF服务实例,然而,当WCF服务的数量比较庞大的时候,应该用那种方式来host服务呢,在《Advanced .Net Remoting》的作者博文中,看到了一个做法,也是我一直想实现的做法,提的要求有两个:

    1、多个服务统一部署和管理,方便加减服务。

    2、WCF独立配置文件,独立于app.config和web.config配置文件。

    做了个简单的例子,大家可以参考参考:

    1、通过 configFileMap.ExeConfigFilename 设置独立配置文件目录。

     //get custom config file name by our rule: config file name = ServiceType.Name
     // var myConfigFileName = this.Description.ServiceType.FullName;
      var myConfigFileName = "WCFSetting";
     //get config file path
      string dir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
      string myConfigFilePath = System.IO.Path.Combine(dir, myConfigFileName + ".config");            
      var configFileMap = new System.Configuration.ExeConfigurationFileMap();
      configFileMap.ExeConfigFilename = myConfigFilePath;
      var conf = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFileMap,ConfigurationUserLevel.None);   
      // ServiceModelSectionGroup svcmod =   (ServiceModelSectionGroup)conf.GetSectionGroup("system.serviceModel");
      var svcmod = System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup(conf);

    2、自定义ServiceHost来实现WCF服务的配置信息从自定义的config中读取。

       

    public class MyServiceHost : ServiceHost
        {
    
            public MyServiceHost(Type t):base(t)
            {
                
            }
            /// <summary>
            /// override ApplyConfiguration to load config from custom file
            /// </summary>
            protected override void ApplyConfiguration()
            {
                //get custom config file name by our rule: config file name = ServiceType.Name
               // var myConfigFileName = this.Description.ServiceType.FullName;
                var myConfigFileName = "WCFSetting";
                //get config file path
                string dir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
                string myConfigFilePath = System.IO.Path.Combine(dir, myConfigFileName + ".config");
                if (!System.IO.File.Exists(myConfigFilePath))
                {
                    base.ApplyConfiguration();
                    return;
                }
                var configFileMap = new System.Configuration.ExeConfigurationFileMap();
                configFileMap.ExeConfigFilename = myConfigFilePath;
                var config = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
                var serviceModel = System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup(config);
                if (serviceModel == null)
                {
                    base.ApplyConfiguration();
                    return;
                }
                foreach (ServiceElement serviceElement in serviceModel.Services.Services)
                {
                    if (serviceElement.Name == this.Description.ServiceType.FullName)
                    {
                        LoadConfigurationSection(serviceElement);
                        return;
                    }
                }
                throw new Exception("there is no service element match the description!");
            }
        }
    

     3、通过static List<ServiceHost>来实现多服务统一管理:

        public class ServiceHostGroup
    {
    static List<ServiceHost> _hosts = new List<ServiceHost>();
    /// <summary>
    /// open and host servcie.
    /// </summary>
    /// <param name="t"></param>
    private static void OpenHost(Type t)
    {
    try
    {
    MyServiceHost hst = new MyServiceHost(t);
    Type ty = hst.Description.ServiceType;//ty
    hst.Open();
    _hosts.Add(hst);

    }
    catch (Exception ex)
    {

    throw;
    }

    }
    public static void StartAllConfiguredServices()
    {
    //get custom config file name by our rule: config file name = ServiceType.Name
    // var myConfigFileName = this.Description.ServiceType.FullName;
    var myConfigFileName = "WCFSetting";
    //get config file path
    string dir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
    string myConfigFilePath = System.IO.Path.Combine(dir, myConfigFileName + ".config");
    var configFileMap = new System.Configuration.ExeConfigurationFileMap();
    configFileMap.ExeConfigFilename = myConfigFilePath;
    var conf = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
    // ServiceModelSectionGroup svcmod = (ServiceModelSectionGroup)conf.GetSectionGroup("system.serviceModel");
    var svcmod = System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup(conf);
    foreach (ServiceElement el in svcmod.Services.Services) {
    string Namespace = el.Name.Substring(0, el.Name.LastIndexOf("."));
    Type svcType = Type.GetType(el.Name + "," + Namespace);
    if (svcType == null) throw new Exception("Invalid Service Type " + el.Name + " in configuration file.");
    OpenHost(svcType);
    }
    }
    public static void CloseAllServices()
    {
    foreach (ServiceHost hst in _hosts)
    {
    hst.Close();
    }
    }
    }

    4、配置文件WCFSetting.config如下:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    <system.serviceModel>
    <behaviors>
    <serviceBehaviors>
    <behavior name="WcfServerBehavior">
    <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点-->
    <serviceMetadata/>
    <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息-->
    <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
    </serviceBehaviors>
    </behaviors>
    <services>
    <service name="BusContractService.BuyFruitService" behaviorConfiguration="WcfServerBehavior">
    <endpoint binding="netTcpBinding" contract="IBusContract.IBuyFruit" bindingConfiguration="ServerBinding" address=""/>
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
    <host>
    <baseAddresses>
    <add baseAddress="net.tcp://localhost:3287/MeiyaWcf/IBuyFruit"/>
    </baseAddresses>
    </host>
    </service>
    </services>
    <bindings>
    <!--安全http-->
    <wsHttpBinding>
    <binding name="NoneSecurity" maxBufferPoolSize="12000000" maxReceivedMessageSize="12000000" useDefaultWebProxy="false">
    <readerQuotas maxStringContentLength="12000000" maxArrayLength="12000000"/>
    <security mode="None"/>
    </binding>
    </wsHttpBinding>
    <!--Tcp-->
    <netTcpBinding>
    <binding name="ServerBinding">
    <security mode="None">
    <transport clientCredentialType="None"/>
    <message clientCredentialType="None"/>
    </security>
    </binding>
    </netTcpBinding>
    </bindings>
    </system.serviceModel>
    </configuration>

    5、在相应的应用程序载体加入代码段:

        ServiceHostGroup.StartAllConfiguredServices();

    至于WCF服务端实例代码就不贴啦,这样做的好处,多个WCF统一管理,WCF配置文件独立,方便管理。当然,代码还有很多需要优化的,等总结的篇章再给个完善点的方案吧。

  • 相关阅读:
    博客园装修行动—我设计的新首页
    按作者名称查看评论
    [新功能]通过RSS阅读收藏夹
    [公告]首页小调整
    时间的格式化
    [公告]将读书心得区改成技术书评区
    [汇报]昨天晚上博客园的程序又出现了问题
    [公告]博客园已经成功迁移至新服务器
    [好消息]博客园乔迁新居
    [公告]博客园程序升级
  • 原文地址:https://www.cnblogs.com/wuyansheng/p/WCF_HOST.html
Copyright © 2020-2023  润新知