编写一个功能函数首先要了解为啥要编这个函数,这个函数有什么用途,这个函数的设计思想是什么,这个函数的算法是什么,这个函数的效用如何?然后,我们再可以评判一下这个函数好在什么地方,不好在什么地方,那些是需要改进的,那些是改进不了的。这样我们才能对这个功能函数有一个深刻的理解和认识。
我会在功能函数分析之中,引深到NSS和EOM概念之中,从而让大家从代码中开始认识NSS和EOM。
今天我们就来讨论一下调用WebService这个函数。
1、 设计思想
1) 一般考虑
一般编写函数是因为开发某个项目和系统的需要。例如,我们开发一个查询系统,在查询系统中需要打开数据库,所以我们就要编写一个打开数据库的函数。
一般人编写调用WebService这个函数,可能出于这个项目有WebService函数,所以要编写一个调用WebService这个函数。
一般考虑的特点:
函数是为特定项目或系统开发而编写的。
这个项目为啥有WebService,是因为这个项目要利用到WebService的特性,例如,非耦合特性、共享的特性。
例如,某系统在注册时,想通过调用WebServie方式,实现用户的登陆(假定WebService函数名为:login)。那么这个login就和系统的宿主程序成了非耦合的关系。
2) NSS考虑
NSS(软件新构架)是给所有项目和系统规划了一个软件构架。它并不是为某一特定项目或系统设计的。也就是说今后所有的项目或系统都会采用NSS。
NSS会提供各种层次的函数,这些函数也是和特定的项目和系统没有关系的。
NSS也提供调用WebService函数。但是这个函数是可以用于所有项目或系统的。
NSS考虑的特点:
函数是为所有项目或系统编写的。
在这里你可以记住NSS中的函数是一个通用函数。
NSS中提供调用WebService函数的原因:
1.给所有项目或系统提供一个宿主和WebSevice之间的接口。
2.这个函数实现了软件功能之间的非耦合联系。
3.这种耦合关系可以解决功能的变更简易性。这种简易性可以导致非项目或系统非宿主开发人员或机构实现这个变更。
4.WebService可提供功能服务,实现最大范围的共享(项目内共享、多项目共享)
3) EOM考虑
EOM要实现企业信息化,必然要能对企业信息化过程中出现的各种问题进行及时的解决。如果应用系统的各种功能函数都是紧耦合,那么当出现功能变更时必须要找到开发此系统的软件公司,或要找到此功能的源程序才能进行变更,然后再重新生成应用系统。当这个约束条件不能满足时,更改就无法完成。因此,EOM必须要能解决上述的问题,这就要求EOM的系统都具备松耦合这种构架,这样当出现问题的时候,用户自己或软件公司只要对宿主以外的功能进行改动就可以解决问题了。
要实现这种松耦合的构架,NSS必须要提供调用WebSerive函数。
因此,调用WebService函数从本质上来说是用来解决满足企业信息化解决各种问题及时性和便易性的要求。
很多程序员在编写程序的时候,只关心程序的功能要求,往往忽略了程序的本质的要求。这样就很难对这个功能有深刻的认识。
另外一个考虑,就是在企业信息化中我们会有很多数据和功能需要共享。这些共享范围可能是企业内部、企业与企业之间。企业内部的各个应用系统也是需要的这些共享的。而WebService方式是实现这种共享方式之一,因此这就会要求NSS采用WebService,进而产生调用WebService函数。
2、 调用WebSerive函数代码
public static object InvokeWebService(string NameSpace,string ClassName,string url, string methodname, object[] args) { string @namespace = NameSpace; string classname = ClassName; System.IO.Stream stream; try { System.Net.WebClient wc = new System.Net.WebClient(); stream = wc.OpenRead(url + "?WSDL"); System.Web.Services.Description.ServiceDescription sd = System.Web.Services.Description.ServiceDescription.Read(stream); System.Web.Services.Description.ServiceDescriptionImporter sdi = new System.Web.Services.Description.ServiceDescriptionImporter(); sdi.AddServiceDescription(sd, "", ""); System.CodeDom.CodeNamespace cn = new System.CodeDom.CodeNamespace(@namespace); System.CodeDom.CodeCompileUnit ccu = new System.CodeDom.CodeCompileUnit(); ccu.Namespaces.Add(cn); sdi.Import(cn, ccu);
Microsoft.CSharp.CSharpCodeProvider csc = new Microsoft.CSharp.CSharpCodeProvider(); System.CodeDom.Compiler.ICodeCompiler icc = csc.CreateCompiler();
System.CodeDom.Compiler.CompilerParameters cplist = new System.CodeDom.Compiler.CompilerParameters(); cplist.GenerateExecutable = false; cplist.GenerateInMemory = true; cplist.ReferencedAssemblies.Add("System.dll"); cplist.ReferencedAssemblies.Add("System.XML.dll"); cplist.ReferencedAssemblies.Add("System.Web.Services.dll"); cplist.ReferencedAssemblies.Add("System.Data.dll");
System.CodeDom.Compiler.CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu); System.Reflection.Assembly assembly = cr.CompiledAssembly; Type t = assembly.GetType(@namespace + "." + classname, true, true); object obj = Activator.CreateInstance(t); System.Reflection.MethodInfo mi = t.GetMethod(methodname); return mi.Invoke(obj, args); } catch (Exception e) { string str = e.Message.Trim(); int s = -8009; //其它连接url错误 Iasg.PublicData.err_message = "出错代码:-8009:其它连接"+url+"错误!"; if (str == "基础连接已经关闭: 无法连接到远程服务器。") { s = -8000;//无法连接到url Iasg.PublicData.err_message = "出错代码:-8000:无法连接到"+url+"!"; } if (str == "参数计数不匹配。") { s = -8001;//参数不匹配 Iasg.PublicData.err_message = "出错代码:-8001:WebService:"+url+"中"+methodname+"的参数不匹配"; } if (str == "未将对象引用设置到对象的实例。") //没有此函数 { s = -8002; Iasg.PublicData.err_message="出错代码:-8002:WebService:"+url+"中没有此函数"+methodname+"!"; } if (str == "远程服务器返回错误: (404) 未找到。") { s = -8003; Iasg.PublicData.err_message = "出错代码:-8003:WebService:" + url + "执行函数" + methodname + "时出现:"+str+"!";
} return s;
}
|
3、 函数的使用
此处给出调用InvokeWebService的实例。
这是一个登陆函数,入口函数是,应用系统代码、用户名、密码、提示框控件。
函数通过调用get_callwsdef函数获取,EomCommonWebService中的login函数的相关参数。
如果没有取到login WebService参数则直接调用紧耦合的eomsv.login(appsys, usr_name, password);函数。
如果取到则通过将这些参数加上其它入口参数调用InvokeWebService函数。实现了login的WebService调用。
对这两种处理方式的返回值进行处理。
public static int login(string appsys, string usr_name, string password, Label lbl_msg) { int s; string web_namespace=""; string web_class_name=""; string web_url=""; string fun_name = "login";
DataSet ds = new DataSet(); s=EomLib.get_callwsdef("EomCommonWebService", fun_name, ref web_namespace, ref web_class_name, ref web_url); if(s==0) { EomCommonWebService.EomCommonWebService1 eomsv= new EomCommonWebService.EomCommonWebService1(); s = eomsv.login(appsys, usr_name, password); } else s = (int)Iasg.IasgLibWeb.InvokeWebService(web_namespace, web_class_name, web_url, fun_name, new object[] { appsys, usr_name, password }); if (s == 0) { lbl_msg.Text = "登录成功!"; string op_content = usr_name + ":登录成功" + IasgLibWeb.p_get_client_ip(); EomLib.db_write_log(usr_name, appsys, "000000001", "04", op_content, ""); s=EomCommonLib.get_login_pubdata(ds, usr_name); return 0; } if(s==-1) { lbl_msg.Text = "用户名或口令出错,登录失败!"; Iasg.PublicData.login_flag = "0"; return -1; } if (s < -1) { lbl_msg.Text =Iasg.PublicData.err_message+"登录失败!"; Iasg.PublicData.login_flag = "0"; return -1; } return -1; } |
4、 函数的分析
大家可以就这个InvokeWebService,对函数名设计、参数设计、功能设计、返回值设计提出更好的建议。
5、WebService方式讨论
采用WebService方式,可以实现函数的非耦合的调用。但是,还有很多问题值得我们去深思去解决。
1) 这种方式也是有所限制的,例如,WebService参数并不是可以适用于所有的数据类型。像非序列化数据类型ListBox等就无法传递。如何解决这个问题。
2) WebService的效率要低于紧耦合函数。
3) WebService在处理大数据交换时产生的效率问题。
4) WebSerivice数据交换的安全性问题。
5) WebService如何设计区分系统出错和功能出错返回值。
6) 如何实现WebService异步调用。
PS:本文我写得非常匆忙,也是第一次写这种文体,逻辑不太清楚,格式也没有调好,自己也不太满意,希望大家多提意见,我会在后面的文章中加以改进。
下篇:《NSS:调用DLL》