首页 > 代码库 > 二十、【.Net开源】EFW框架核心类库之WebService服务
二十、【.Net开源】EFW框架核心类库之WebService服务
回《【开源】EFW框架系列文章索引》
EFW框架源代码下载V1.1:http://pan.baidu.com/s/1qWJjo3U
EFW框架实例源代码下载:http://pan.baidu.com/s/1o6MAKCa
EFW框架中的WebService服务开发方式与传统的net项目中开发不太一样,传统的开发方式虽然也挺简单但在后面的发布部署还是挺麻烦的,而在EFW框架中开发Webservice就跟编写普通的C#代码一样,并不需要单独建WebService服务项目,不需要Asmx文件;所以发布WebService只要把编译好的Dll拷贝到Web程序目录中就行了;
另外我建议尽量少用WebService服务来开发业务功能,系统内部的功能实现用前三章的控制器方式就可以搞定,只有在需要与外部系统做接口时,可以用它来开发相关接口程序;
本章主要内容通过解读框架源代码来学习WebService服务是怎么实现的,以及学习这种设计模式;
本文要点:
1.如何开发WebService系统接口
2.WebService服务的设计思路
3.WebService服务基类的AbstractService的实现
4.通过服务名称解析WebService对象的WebServiceInvoker类的实现
5.利用wsdl生成WebService生成代理类
WebService服务源代码目录结构:
EFW框架控制器设计图:
1.如何开发WebService系统接口
如上图,Books项目中实现了书籍实例的一些Webservice系统接口,bookWebService.cs文件是和逻辑层代码放在一起的,并不需要单独建一个Webservice服务项目,也不需要建到Web项目中;对比一下上图普通的WebService服务,不需要BookService.asmx文件;
见上图,WebService服务接口的使用跟普通的Net 系统中的WebService是一样的,地址栏中输入WebService服务对象的名称就可以调用,但是注意名称一样但是必须用asmx为后缀名,因为服务器只解析这种后缀名称的文件映射到后台的WebService服务;上图开放了两个WebService服务方法SaveBook和SearchBook。
2.WebService服务的设计思路
当初设计这种开发模式的目的就是为了减少项目的个数,到现在整个框架的项目只有5个,而且只有5个项目却包括了Web、Winform和WCF三种系统的开发;这都是为了秉承框架中的核心思想“简洁”,结构的简单明了,代码的整洁干净;所以为了几个WebService接口而增加一个WebService项目觉得太划不来了,所以开始思考如何实现,后来在网上看到了一个帖子讲动态调用WebService服务的,具体哪个帖子现在找不到了,反正我就借鉴了过来融入到了框架中,终于解决了这个难题;WebServiceInvoker类就是动态解析WebService服务的实现代码;所有WebService服务对象都必须继承AbstractService基类,AbstractService基类封装了WebService服务公共的处理功能;
3.WebService服务基类的AbstractService的实现
AbstractService文件
1 /// <summary> 2 /// WebService基类 3 /// </summary> 4 public class AbstractService : WebService, INewObject, INewDao 5 { 6 7 private AbstractDatabase _oleDb = null; 8 private IUnityContainer _container = null; 9 public AbstractDatabase oleDb10 {11 get12 {13 if (_oleDb == null)14 {15 _oleDb = FactoryDatabase.GetDatabase();16 _container = AppGlobal.container;17 }18 return _oleDb;19 }20 }21 22 //声明Soap头实例23 public GlobalParam param = new GlobalParam();24 25 #region IBindDb 成员26 27 public void BindDb(AbstractDatabase Db, IUnityContainer container)28 {29 _oleDb = Db;30 _container = container;31 }32 33 public T BindDb<T>(T model)34 {35 (model as IbindDb).BindDb(_oleDb, _container);36 return model;37 }38 39 public List<T> ListBindDb<T>(List<T> list)40 {41 for (int i = 0; i < list.Count; i++)42 {43 (list[i] as IbindDb).BindDb(_oleDb, _container);44 }45 return list;46 }47 48 public AbstractDatabase GetDb()49 {50 return _oleDb;51 }52 53 public IUnityContainer GetUnityContainer()54 {55 return _container;56 }57 58 #endregion59 60 #region INewObject 成员61 public T NewObject<T>()62 {63 T t = FactoryModel.GetObject<T>(_oleDb, _container, null);64 return t;65 }66 67 public T NewObject<T>(string unityname)68 {69 T t = FactoryModel.GetObject<T>(_oleDb, _container, unityname);70 return t;71 }72 73 #endregion74 75 #region INewDao 成员76 77 public T NewDao<T>()78 {79 T t = FactoryModel.GetObject<T>(_oleDb, _container, null);80 return t;81 }82 83 public T NewDao<T>(string unityname)84 {85 T t = FactoryModel.GetObject<T>(_oleDb, _container, unityname);86 return t;87 }88 89 #endregion90 91 }
AbstractService基类的功能封装包括:
1)数据库操作对象oleDb,可以直接在WebService服务中编写SQL语句操作数据库
2)实例化ObjectModel对象和Dao对象的方法,在WebService服务中实例化对象不能用new关键字,只能用NewObject()和NewDao()内置方法;
4.通过服务名称解析WebService对象的WebServiceInvoker类的实现
WebServiceInvoker文件
1 /// <summary> 2 /// WebService处理对象 3 /// </summary> 4 public class WebServiceInvoker : IHttpHandlerFactory 5 { 6 private Type GetWebService(HttpRequest request, string serviceName) 7 { 8 Type serviceType = null; 9 //for (int i = 0; i < AppGlobal.BusinessDll.Count; i++)10 //{11 // Assembly asmb = Assembly.LoadFrom(AppGlobal.AppRootPath + "bin\\" + AppGlobal.BusinessDll[i].Trim());12 // if (asmb != null)13 // {14 // Type ts = asmb.GetType(serviceName);15 // if (ts != null)16 // {17 // serviceType = ts;18 // break;19 // }20 // }21 //}22 23 List<Type> cmd = (List<Type>)AppGlobal.cache.GetData("cmdWebService");24 serviceType = cmd.Find(x => x.Name == serviceName);25 return serviceType;26 }27 28 public void ReleaseHandler(IHttpHandler handler)29 {30 var wshf = new System.Web.Services.Protocols.WebServiceHandlerFactory();31 wshf.ReleaseHandler(handler);32 }33 34 public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)35 {36 var webServiceType = GetWebService(context.Request, GetServiceName(url));37 var wshf = new System.Web.Services.Protocols.WebServiceHandlerFactory();38 var coreGetHandler = typeof(WebServiceHandlerFactory).GetMethod("CoreGetHandler", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);39 var httpHandler = (IHttpHandler)coreGetHandler.Invoke(wshf, new object[] { webServiceType, context, context.Request, context.Response });40 return httpHandler;41 }42 43 public static string GetServiceName(string url)44 {45 int index = url.LastIndexOf("/");46 int index2 = url.Substring(index).IndexOf(".");47 return url.Substring(index + 1, index2 - 1);48 }49 50 public static void LoadWebService(List<string> BusinessDll, ICacheManager cache)51 {52 List<Type> webserviceList = new List<Type>();53 54 for (int k = 0; k < BusinessDll.Count; k++)55 {56 System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(EFWCoreLib.CoreFrame.Init.AppGlobal.AppRootPath + "bin/" + BusinessDll[k]);57 Type[] types = assembly.GetTypes();58 for (int i = 0; i < types.Length; i++)59 {60 WebServiceAttribute[] webS = ((WebServiceAttribute[])types[i].GetCustomAttributes(typeof(WebServiceAttribute), true));61 if (webS.Length > 0)62 {63 webserviceList.Add(types[i]);64 }65 }66 }67 68 cache.Add("cmdWebService", webserviceList);69 }70 }
WebServiceInvoker对象继承IHttpHandlerFactory接口并实现接口方法GetHandler和ReleaseHandler,还要在Web.Config配置文件中进行配置;
5.利用wsdl生成WebService生成代理类
生成命令:wsdl /language:c# /out:c:\bookWebService.cs http://localhost:51796/bookWebService.asmx?WSDL
操作步骤:
1)打开Net命令工具
2)复制上面的wsdl命令并执行,提示写入“c:\bookWebService.cs ”成功
3)再把“c:\bookWebService.cs ”的文件拷贝到需要调用WebService接口的项目中使用就可以了;
bookWebService文件
//------------------------------------------------------------------------------// <auto-generated>// 此代码由工具生成。// 运行时版本:2.0.50727.5477//// 对此文件的更改可能会导致不正确的行为,并且如果// 重新生成代码,这些更改将会丢失。// </auto-generated>//------------------------------------------------------------------------------using System;using System.ComponentModel;using System.Data;using System.Diagnostics;using System.Web.Services;using System.Web.Services.Protocols;using System.Xml.Serialization;// // 此源代码由 wsdl 自动生成, Version=2.0.50727.1432。// /// <remarks/>[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432")][System.Diagnostics.DebuggerStepThroughAttribute()][System.ComponentModel.DesignerCategoryAttribute("code")][System.Web.Services.WebServiceBindingAttribute(Name="bookWebServiceSoap", Namespace="http://tempuri.org/")][System.Xml.Serialization.XmlIncludeAttribute(typeof(MarshalByRefObject))]public partial class bookWebService : System.Web.Services.Protocols.SoapHttpClientProtocol { private System.Threading.SendOrPostCallback SaveBookOperationCompleted; private System.Threading.SendOrPostCallback SearchBookOperationCompleted; /// <remarks/> public bookWebService() { this.Url = "http://localhost:51796/bookWebService.asmx"; } /// <remarks/> public event SaveBookCompletedEventHandler SaveBookCompleted; /// <remarks/> public event SearchBookCompletedEventHandler SearchBookCompleted; /// <remarks/> [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/SaveBook", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public void SaveBook(Book book) { this.Invoke("SaveBook", new object[] { book}); } /// <remarks/> public System.IAsyncResult BeginSaveBook(Book book, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("SaveBook", new object[] { book}, callback, asyncState); } /// <remarks/> public void EndSaveBook(System.IAsyncResult asyncResult) { this.EndInvoke(asyncResult); } /// <remarks/> public void SaveBookAsync(Book book) { this.SaveBookAsync(book, null); } /// <remarks/> public void SaveBookAsync(Book book, object userState) { if ((this.SaveBookOperationCompleted == null)) { this.SaveBookOperationCompleted = new System.Threading.SendOrPostCallback(this.OnSaveBookOperationCompleted); } this.InvokeAsync("SaveBook", new object[] { book}, this.SaveBookOperationCompleted, userState); } private void OnSaveBookOperationCompleted(object arg) { if ((this.SaveBookCompleted != null)) { System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); this.SaveBookCompleted(this, new System.ComponentModel.AsyncCompletedEventArgs(invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); } } /// <remarks/> [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/SearchBook", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public System.Data.DataTable SearchBook(string schar, int flag) { object[] results = this.Invoke("SearchBook", new object[] { schar, flag}); return ((System.Data.DataTable)(results[0])); } /// <remarks/> public System.IAsyncResult BeginSearchBook(string schar, int flag, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("SearchBook", new object[] { schar, flag}, callback, asyncState); } /// <remarks/> public System.Data.DataTable EndSearchBook(System.IAsyncResult asyncResult) { object[] results = this.EndInvoke(asyncResult); return ((System.Data.DataTable)(results[0])); } /// <remarks/> public void SearchBookAsync(string schar, int flag) { this.SearchBookAsync(schar, flag, null); } /// <remarks/> public void SearchBookAsync(string schar, int flag, object userState) { if ((this.SearchBookOperationCompleted == null)) { this.SearchBookOperationCompleted = new System.Threading.SendOrPostCallback(this.OnSearchBookOperationCompleted); } this.InvokeAsync("SearchBook", new object[] { schar, flag}, this.SearchBookOperationCompleted, userState); } private void OnSearchBookOperationCompleted(object arg) { if ((this.SearchBookCompleted != null)) { System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); this.SearchBookCompleted(this, new SearchBookCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); } } /// <remarks/> public new void CancelAsync(object userState) { base.CancelAsync(userState); }}/// <remarks/>[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432")][System.SerializableAttribute()][System.Diagnostics.DebuggerStepThroughAttribute()][System.ComponentModel.DesignerCategoryAttribute("code")][System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]public partial class Book : AbstractEntity { private int idField; private string bookNameField; private decimal buyPriceField; private System.DateTime buyDateField; private int flagField; /// <remarks/> public int Id { get { return this.idField; } set { this.idField = value; } } /// <remarks/> public string BookName { get { return this.bookNameField; } set { this.bookNameField = value; } } /// <remarks/> public decimal BuyPrice { get { return this.buyPriceField; } set { this.buyPriceField = value; } } /// <remarks/> public System.DateTime BuyDate { get { return this.buyDateField; } set { this.buyDateField = value; } } /// <remarks/> public int Flag { get { return this.flagField; } set { this.flagField = value; } }}/// <remarks/>[System.Xml.Serialization.XmlIncludeAttribute(typeof(Book))][System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432")][System.SerializableAttribute()][System.Diagnostics.DebuggerStepThroughAttribute()][System.ComponentModel.DesignerCategoryAttribute("code")][System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]public abstract partial class AbstractEntity : AbstractBusines {}/// <remarks/>[System.Xml.Serialization.XmlIncludeAttribute(typeof(AbstractEntity))][System.Xml.Serialization.XmlIncludeAttribute(typeof(Book))][System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432")][System.SerializableAttribute()][System.Diagnostics.DebuggerStepThroughAttribute()][System.ComponentModel.DesignerCategoryAttribute("code")][System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]public abstract partial class AbstractBusines : MarshalByRefObject {}/// <remarks/>[System.Xml.Serialization.XmlIncludeAttribute(typeof(AbstractBusines))][System.Xml.Serialization.XmlIncludeAttribute(typeof(AbstractEntity))][System.Xml.Serialization.XmlIncludeAttribute(typeof(Book))][System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432")][System.SerializableAttribute()][System.Diagnostics.DebuggerStepThroughAttribute()][System.ComponentModel.DesignerCategoryAttribute("code")][System.Xml.Serialization.XmlTypeAttribute(Namespace="http://tempuri.org/")]public abstract partial class MarshalByRefObject {}/// <remarks/>[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432")]public delegate void SaveBookCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e);/// <remarks/>[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432")]public delegate void SearchBookCompletedEventHandler(object sender, SearchBookCompletedEventArgs e);/// <remarks/>[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432")][System.Diagnostics.DebuggerStepThroughAttribute()][System.ComponentModel.DesignerCategoryAttribute("code")]public partial class SearchBookCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { private object[] results; internal SearchBookCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : base(exception, cancelled, userState) { this.results = results; } /// <remarks/> public System.Data.DataTable Result { get { this.RaiseExceptionIfNecessary(); return ((System.Data.DataTable)(this.results[0])); } }}
二十、【.Net开源】EFW框架核心类库之WebService服务