搭建自己的框架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