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