搭建自己的框架WedeNet(五)
WedeNet2018.WedeWcfServices-WCF服务层:
结构如下:
就是定义了服务契约接口和服务类,以OrderServices为例,如下:
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; using WedeNet2018.Infrastructure; using WedeNet2018.Infrastructure.WcfEntities; namespace WedeNet2018.WedeWcfServices { [ServiceContract] public interface IOrderServices { [OperationContract] OrdersContract[] GetOrders( int orderType); [OperationContract] OrdersContract GetOrdersStr( int orderType); [OperationContract] void AddOrder(OrdersContract order); [OperationContract] void UpdateOrder(OrdersContract order); [OperationContract] void DeleteOrder( int id); } } |
实现类:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ServiceModel; using WedeNet2018.Infrastructure; using WedeNet2018.BussinessLogic; using Ninject; using WedeNet2018.Infrastructure.Components; using SFast; using WedeNet2018.Infrastructure.WcfEntities; namespace WedeNet2018.WedeWcfServices.Impl { [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)] public class OrderServices : IOrderServices { private OrdersBussinessLogic orderBll { get ; set ; } public OrderServices() { IKernel ninjectKernel = new StandardKernel(); ninjectKernel.Bind<AbsWedeDBContex>().To<WedeDBContex>(); ninjectKernel.Bind<IWedeUnitOfWorks>().To<WedeUnitOfWorks<AbsWedeDBContex>>().InSingletonScope(); ninjectKernel.Bind<OrdersBussinessLogic>().ToSelf(); orderBll = ninjectKernel.Get<OrdersBussinessLogic>(); } public OrdersContract[] GetOrders( int orderType) { OrdersContract[] ret = null ; try { IList<Orders> orders = orderBll.GetOrders(orderType).ToList(); IList<OrdersContract> ordersContracts = new List<OrdersContract>(); orders.ForEach(o => ordersContracts.Add( new OrdersContract() { Id=o.Id,OrderSn=o.OrderSn})); ret = ordersContracts.ToArray(); } catch (Exception ex) { } return ret; } public OrdersContract GetOrdersStr( int orderType) { OrdersContract ret = new OrdersContract(); try { Orders order = orderBll.GetOrders(orderType).FirstOrDefault(); if (order != null ) { ret.Id = order.Id; ret.OrderSn = order.OrderSn; } } catch (Exception ex) { } return ret; } public void AddOrder(OrdersContract order) { } public void UpdateOrder(OrdersContract order) { } public void DeleteOrder( int id) { } } } |
这里需要说明的是,服务实现类的构造函数里,也有NInject的映射配置,当然这里是按需配置的。
WedeNet2018.ServiceHosting-WCF服务寄宿层:
结构如下:
(需要说明的是,本层是一个windows服务)
服务寄宿层的App.config里配置WCF相关配置信息,如:
<?xml version= "1.0" encoding= "utf-8" ?> <configuration> <configSections> <section name= "ValidServices" type= "WedeNet2018.ServiceHosting.ValidServicesSection, WedeNet2018.ServiceHosting" /> </configSections> <connectionStrings> <add name= "constring" connectionString= "Data Source=.;Initial Catalog=MVCEF1;User ID=sa;Password=11111111;" providerName= "System.Data.SqlClient" /> <add name= "xf0816Constring" connectionString= "Data Source=172.18.105.63;Initial Catalog=Xinfu0816;User ID=test;Password=xinfuka;" providerName= "System.Data.SqlClient" /> </connectionStrings> <startup> <supportedRuntime version= "v4.0" sku= ".NETFramework,Version=v4.5" /> </startup> <ValidServices> <Services> <add Type= "WedeNet2018.WedeWcfServices.Impl.OrderServices,WedeNet2018.WedeWcfServices" /> <add Type= "WedeNet2018.WedeWcfServices.Impl.UserServices,WedeNet2018.WedeWcfServices" /> </Services> </ValidServices> <system.serviceModel> <behaviors> <endpointBehaviors> <behavior name= "endpointBehavior" > <dataContractSerializer /> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior name= "WedeNetServerBehavior_order" > <serviceMetadata httpGetEnabled= "true" httpGetUrl= "http://localhost:9999/WedeWcfServices/orderServices/metadata" /> <serviceDebug httpHelpPageEnabled= "true" httpsHelpPageEnabled= "true" includeExceptionDetailInFaults= "true" /> </behavior> <behavior name= "WedeNetServerBehavior_user" > <serviceMetadata httpGetEnabled= "true" httpGetUrl= "http://localhost:9999/WedeWcfServices/userServices/metadata" /> <serviceDebug httpHelpPageEnabled= "true" httpsHelpPageEnabled= "true" includeExceptionDetailInFaults= "true" /> </behavior> </serviceBehaviors> </behaviors> <bindings> <wsHttpBinding> <binding name= "WedeWcfBinding" closeTimeout= "00:01:00" openTimeout= "00:01:00" receiveTimeout= "00:10:00" sendTimeout= "00:01:00" bypassProxyOnLocal= "false" transactionFlow= "false" hostNameComparisonMode= "StrongWildcard" maxBufferPoolSize= "524288" maxReceivedMessageSize= "99965536" messageEncoding= "Text" textEncoding= "utf-8" useDefaultWebProxy= "true" allowCookies= "false" > <readerQuotas maxDepth= "32" maxStringContentLength= "8192" maxArrayLength= "16384" maxBytesPerRead= "4096" maxNameTableCharCount= "16384" /> <reliableSession ordered= "true" inactivityTimeout= "00:10:00" enabled= "false" /> <security mode= "None" > <transport clientCredentialType= "Windows" proxyCredentialType= "None" realm= "" /> <message clientCredentialType= "Windows" negotiateServiceCredential= "true" /> </security> </binding> </wsHttpBinding> </bindings> <services> <service behaviorConfiguration= "WedeNetServerBehavior_order" name= "WedeNet2018.WedeWcfServices.Impl.OrderServices" > <endpoint address= "http://localhost:9999/WedeWcfServices/orderServices" behaviorConfiguration= "endpointBehavior" binding= "wsHttpBinding" bindingConfiguration= "WedeWcfBinding" contract= "WedeNet2018.WedeWcfServices.IOrderServices" > <identity> <dns value= "localhost" /> </identity> </endpoint> </service> <service behaviorConfiguration= "WedeNetServerBehavior_user" name= "WedeNet2018.WedeWcfServices.Impl.UserServices" > <endpoint address= "http://localhost:9999/WedeWcfServices/userServices" behaviorConfiguration= "endpointBehavior" binding= "wsHttpBinding" bindingConfiguration= "WedeWcfBinding" contract= "WedeNet2018.WedeWcfServices.IUserServices" > <identity> <dns value= "localhost" /> </identity> </endpoint> </service> </services> </system.serviceModel> </configuration> |
ValidServices配置节点是批量寄宿服务时,读取配置的服务信息的,其实现如下:
using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WedeNet2018.ServiceHosting { /// <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" ]; } } } } |
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 System.Threading.Tasks; using WedeNet2018.Common; namespace WedeNet2018.ServiceHosting { 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; LoggerHelper.ServicesLogger.Info( "typeToLoad:" + typeToLoad); // Load the assembly dynamic string assemblyName = typeToLoad.Substring(typeToLoad.IndexOf( ',' ) + 1); LoggerHelper.ServicesLogger.Info( "assemblyName:" + assemblyName); Assembly.Load(assemblyName); Type svcType = Type.GetType(typeToLoad); if (svcType == null ) { string errInfo = string .Format( "Invalid Service Type \"{0}\" in configuration file." , typeToLoad); LoggerHelper.ServicesLogger.Info(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()); } LoggerHelper.ServicesLogger.Info( 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; LoggerHelper.ServicesLogger.Info( string .Format( "Service \"{0}\" stopped." , svcName)); } } } |
实现批量服务寄宿的代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Linq; using System.ServiceModel; using System.ServiceProcess; using System.Text; using System.Threading.Tasks; using WedeNet2018.Common; using WedeNet2018.WedeWcfServices.Impl; namespace WedeNet2018.ServiceHosting { public partial class WedeNet2018Services : ServiceBase { static List<ServiceHost> _allHosts = new List<ServiceHost>(); public WedeNet2018Services() { InitializeComponent(); } protected override void OnStart( string [] args) { try { ServiceManager.StartAllValidServices(); LoggerHelper.ServicesLogger.Info( "All WCF services started." ); } catch (ApplicationException ex) { LoggerHelper.ServicesLogger.Info(ex.Message); } } protected override void OnStop() { try { ServiceManager.CloseAllServices(); LoggerHelper.ServicesLogger.Info( "All WCF services stopped." ); } catch (ApplicationException ex) { LoggerHelper.ServicesLogger.Info(ex.Message); } } } } |
最后,服务的安装和卸载.bat代码:
service_install.bat
@echo off set /p var =是否要安装 WCF 服务(Y/N): if "%var%" == "Y" ( goto install) else ( goto batexit) :install copy C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe InstallUtil.exe /Y call InstallUtil.exe E:\个人\Wede框架\WedeNet2018\WedeNet2018\WedeNet2018.ServiceHosting\bin\Debug\WedeNet2018.ServiceHosting.exe call sc start "WedeNet2018Services" pause :batexit exit |
service_unInstall.bat
@echo off set /p var =是否要卸载 WCF服务(Y/N): if "%var%" == "Y" ( goto uninstall) else ( goto batexit) :uninstall copy C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe InstallUtil.exe /Y call InstallUtil.exe /u E:\个人\Wede框架\WedeNet2018\WedeNet2018\WedeNet2018.ServiceHosting\bin\Debug\WedeNet2018.ServiceHosting.exe pause :batexit exit |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端