回《【開源】EFW框架系列文章索引》 html
EFW框架源代碼下載V1.1:http://pan.baidu.com/s/1qWJjo3Uweb
EFW框架實例源代碼下載:http://pan.baidu.com/s/1o6MAKCa數據庫
EFW框架中的WebService服務開發方式與傳統的net項目中開發不太同樣,傳統的開發方式雖然也挺簡單但在後面的發佈部署仍是挺麻煩的,而在EFW框架中開發Webservice就跟編寫普通的C#代碼同樣,並不須要單獨建WebService服務項目,不須要Asmx文件;因此發佈WebService只要把編譯好的Dll拷貝到Web程序目錄中就好了;c#
另外我建議儘可能少用WebService服務來開發業務功能,系統內部的功能實現用前三章的控制器方式就能夠搞定,只有在須要與外部系統作接口時,能夠用它來開發相關接口程序;設計模式
本章主要內容經過解讀框架源代碼來學習WebService服務是怎麼實現的,以及學習這種設計模式;服務器
本文要點:app
1.如何開發WebService系統接口框架
2.WebService服務的設計思路async
3.WebService服務基類的AbstractService的實現ide
4.經過服務名稱解析WebService對象的WebServiceInvoker類的實現
5.利用wsdl生成WebService生成代理類
WebService服務源代碼目錄結構:
EFW框架控制器設計圖:
如上圖,Books項目中實現了書籍實例的一些Webservice系統接口,bookWebService.cs文件是和邏輯層代碼放在一塊兒的,並不須要單獨建一個Webservice服務項目,也不須要建到Web項目中;對比一下上圖普通的WebService服務,不須要BookService.asmx文件;
見上圖,WebService服務接口的使用跟普通的Net 系統中的WebService是同樣的,地址欄中輸入WebService服務對象的名稱就能夠調用,可是注意名稱同樣可是必須用asmx爲後綴名,由於服務器只解析這種後綴名稱的文件映射到後臺的WebService服務;上圖開放了兩個WebService服務方法SaveBook和SearchBook。
當初設計這種開發模式的目的就是爲了減小項目的個數,到如今整個框架的項目只有5個,並且只有5個項目卻包括了Web、Winform和WCF三種系統的開發;這都是爲了秉承框架中的核心思想「簡潔」,結構的簡單明瞭,代碼的整潔乾淨;因此爲了幾個WebService接口而增長一個WebService項目以爲太划不來了,因此開始思考如何實現,後來在網上看到了一個帖子講動態調用WebService服務的,具體哪一個帖子如今找不到了,反正我就借鑑了過來融入到了框架中,終於解決了這個難題;WebServiceInvoker類就是動態解析WebService服務的實現代碼;全部WebService服務對象都必須繼承AbstractService基類,AbstractService基類封裝了WebService服務公共的處理功能;
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 oleDb 10 { 11 get 12 { 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 #endregion 59 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 #endregion 74 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 #endregion 90 91 }
AbstractService基類的功能封裝包括:
1)數據庫操做對象oleDb,能夠直接在WebService服務中編寫SQL語句操做數據庫
2)實例化ObjectModel對象和Dao對象的方法,在WebService服務中實例化對象不能用new關鍵字,只能用NewObject()和NewDao()內置方法;
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配置文件中進行配置;
生成命令: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])); } } }