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配置文件独立,方便管理。当然,代码还有很多需要优化的,等总结的篇章再给个完善点的方案吧。

原文地址:https://www.cnblogs.com/wuyansheng/p/WCF_HOST.html