搭建自己的框架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:WindowsMicrosoft.NETFramework64v4.0.30319InstallUtil.exe  InstallUtil.exe /Y
call InstallUtil.exe E:个人Wede框架WedeNet2018WedeNet2018WedeNet2018.ServiceHostinginDebugWedeNet2018.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:WindowsMicrosoft.NETFramework64v4.0.30319InstallUtil.exe  InstallUtil.exe /Y
call InstallUtil.exe /u E:个人Wede框架WedeNet2018WedeNet2018WedeNet2018.ServiceHostinginDebugWedeNet2018.ServiceHosting.exe
pause
 
:batexit
exit
原文地址:https://www.cnblogs.com/zhaow/p/9401133.html