WCF寄宿windows服务二
如果有很多WCF服务需要寄宿,需要额外做一些工作:
总体思路是:先把这些WCF服务的程序集打包,然后利用反射加载各个WCF服务的程序集,按顺序一个一个寄宿。
先来看看我们需要寄宿的WCF服务:
实现步骤:
1、配置文件中打包这些WCF程序集信息。
2、需要自定义配置节点以及实现读取自定义配置节点的方法。
在configSections节点增加配置:
<section name= "ValidServices" type= "Mdtit.XXX.Mall.Hosting.ValidServicesSection, Mdtit.XXX.Mall.Hosting" /> |
配置处理类实现如下:
using System; using System.Collections.Generic; using System.Reflection; using System.Configuration; using System.ServiceModel.Configuration; using System.ServiceModel; using System.Xml; using System.Xml.Serialization; using System.IO; using System.ServiceModel.Description; using System.Text; using Mdtit.XXX.Mall.Common; namespace Mdtit.XXX.Mall.Hosting { /// <summary> /// Custom configuration section for valid service setting /// </summary> internal class ValidServicesSection : ConfigurationSection { [ConfigurationProperty( "Services" )] public ValidServiceCollection ValidServices { get { return this [ "Services" ] as ValidServiceCollection; } } } /// <summary> /// Custom configuration element collection for valid service setting /// </summary> internal class ValidServiceCollection : ConfigurationElementCollection { protected override ConfigurationElement CreateNewElement() { return new ValidService(); } protected override object GetElementKey(ConfigurationElement element) { return ((ValidService)element).Type; } } /// <summary> /// Custom configuration element for valid service setting /// </summary> internal class ValidService : ConfigurationElement { [ConfigurationProperty( "Type" )] public string Type { get { return ( string ) this [ "Type" ]; } } } } |
3、windows服务的Main函数
static class Program { /// <summary> /// The main entry point for the application. /// </summary> static void Main() { ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new XXXService() }; ServiceBase.Run(ServicesToRun); } } |
4、windows服务类:XXXService
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Linq; using System.ServiceProcess; using System.Text; using Mdtit.XXX.Mall.Hosting; using Mdtit.XXX.Mall.Common; using System.ServiceModel; namespace Mdtit.XXX.Mall.Hosting.Service { public partial class XXXService : ServiceBase { /// <summary> /// All avalilable services. /// </summary> static List<ServiceHost> _allHosts = new List<ServiceHost>(); public XXXService() { InitializeComponent(); } protected override void OnStart( string [] args) { try { ServiceManager.StartAllValidServices(); LogHelper.LogInformation( "All WCF services started." ); } catch (ApplicationException ex) { LogHelper.LogInformation(ex.Message); } } protected override void OnStop() { try { ServiceManager.CloseAllServices(); LogHelper.LogInformation( "All WCF services stopped." ); } catch (ApplicationException ex) { LogHelper.LogInformation(ex.Message); } } } } |
其中,ServiceManager.StartAllValidServices() 和 ServiceManager.CloseAllServices()是用来批量处理WCF服务的。
5、ServiceManager类实现如下:
using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Reflection; using System.ServiceModel; using System.ServiceModel.Description; using System.Text; using Mdtit.XXX.Mall.Common; namespace Mdtit.XXX.Mall.Hosting { /// <summary> /// Helper class to start/stop services /// </summary> internal class ServiceManager { /// <summary> /// Container for all valid services /// </summary> static List<ServiceHost> _AllHosts = new List<ServiceHost>(); /// <summary> /// Start all valid services. /// </summary> public static void StartAllValidServices() { string entryLocation = Assembly.GetEntryAssembly().Location; Configuration conf = ConfigurationManager.OpenExeConfiguration(entryLocation); ValidServicesSection validServiceSettings = ConfigurationManager.GetSection( "ValidServices" ) as ValidServicesSection; if (validServiceSettings != null ) { foreach (ValidService validService in validServiceSettings.ValidServices) { string typeToLoad = validService.Type; // Load the assembly dynamic string assemblyName = typeToLoad.Substring(typeToLoad.IndexOf( ',' ) + 1); Assembly.Load(assemblyName); Type svcType = Type.GetType(typeToLoad); if (svcType == null ) { string errInfo = string .Format( "Invalid Service Type \"{0}\" in configuration file." , typeToLoad); LogHelper.LogError(errInfo); throw new ApplicationException(errInfo); } else { OpenHost(svcType); } } } else { throw new ApplicationException( "Application configuration for WCF services not found!" ); } } /// <summary> /// Create a host for a specified wcf service; /// </summary> /// <param name="t"></param> private static void OpenHost(Type t) { ServiceHost host = new ServiceHost(t); host.Opened += new EventHandler(hostOpened); host.Closed += new EventHandler(hostClosed); host.Open(); _AllHosts.Add(host); } /// <summary> /// Close all services /// </summary> public static void CloseAllServices() { foreach (ServiceHost host in _AllHosts) { if (host.State != CommunicationState.Closed) { host.Close(); } } } /// <summary> /// Event handler for host opened /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void hostOpened( object sender, EventArgs e) { ServiceDescription svcDesc = ((ServiceHost)sender).Description; string svcName = svcDesc.Name; StringBuilder allUri = new StringBuilder(); foreach (ServiceEndpoint endPoint in svcDesc.Endpoints) { allUri.Append(endPoint.ListenUri.ToString()); } LogHelper.LogInformation( string .Format( "Service \"{0}\" started with url: {1}" , svcName, allUri.ToString())); } /// <summary> /// Event handler for host closed /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void hostClosed( object sender, EventArgs e) { ServiceDescription svcDesc = ((ServiceHost)sender).Description; string svcName = svcDesc.Name; LogHelper.LogInformation( string .Format( "Service \"{0}\" stopped." , svcName)); } } } |
6、开始寄宿
以管理员身份运行我们前面写好的windows服务程序:
结果:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端