博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
msdn 中MethodBase.Invoke 方法 介绍中的坑
阅读量:6432 次
发布时间:2019-06-23

本文共 13466 字,大约阅读时间需要 44 分钟。

模块开发总结:
c#动态调用webservices
来自网络及使用心得。

msdn:
MethodBase.Invoke 方法 (Object, Object[])
使用指定的参数调用当前实例所表示的方法或构造函数。

public Object Invoke (    Object obj,    Object[] parameters)
参数
obj

对其调用方法或构造函数的对象。如果方法是静态的,则忽略此参数。如果构造函数是静态的,则此参数必须为 空引用(在 Visual Basic 中为 Nothing) 或定义该构造函数的类的实例。

parameters

调用的方法或构造函数的参数列表。这是一个对象数组,这些对象与要调用的方法或构造函数的参数具有相同的数量、顺序和类型。如果没有任何参数,则parameters 应为 空引用(在 Visual Basic 中为 Nothing)。

如果此实例所表示的方法或构造函数采用 ref 参数(在 Visual Basic 中为 ByRef),使用此函数调用该方法或构造函数时,该参数不需要任何特殊属性。如果数组中的对象未用值来显式初始化,则该对象将包含该对象类型的默认值。对于引用类型的元素,该值为 空引用(在 Visual Basic 中为 Nothing)。对于值类型的元素,该值为 0、0.0 或 false,具体取决于特定的元素类型。

返回值

一个对象,包含被调用方法的返回值,如果调用的是构造函数,则为 空引用(在 Visual Basic 中为 Nothing)。

 

xfire中提供的webservices(创建过程见baidu,很多很好)

public String invokedUseArray(String[] msgArray){    for (int i = 0; i < msgArray.length; i++) {        System.out.println(msgArray[i]);    }    return "1";}public String invokedUseString(String title,String desc){    System.out.println(title+"\t"+desc);    return "1";}

c#调用

string webserviceUrl==http://localhost:8080/bomcbpinterface/services/CreateGevtIncidentService;string title =”title”;string desc =”description”;string methodNameArray=”invokedUseArray”;string[] argsArray={title,desc}object result1 = WebServiceHelper.InvokeWebService(webserviceUrl,null,methodNameArray,new object[]{argsArray});//容易出错,报参数个数不对的异常string methodNameString=”invokedUseString”object result2 = WebServiceHelper.InvokeWebService(webserviceUrl, null, methodNameString,argsArray);//容易出错,报参数个数不对的异常或object result2 = WebServiceHelper.InvokeWebService(webserviceUrl, null, methodNameString,new object[]{title,desc});//容易出错,报参数个数不对的异常

 

Utility:

需要添加引用:System.Web.Service
需要将.net 4.0 framework client profile,我们应该将它改成 .net 4.0 framework(VS2010)

具体步骤:

1. 从目标 URL 下载 WSDL 数据。
2. 使用 ServiceDescription 创建和格式化 WSDL 文档文件。
3. 使用 ServiceDescriptionImporter 创建客户端代理类。
4. 使用 CodeDom 动态创建客户端代理类程序集。
5. 利用反射调用相关 WebService 方法。

具体代码:

class WebServiceHelper    {        #region InvokeWebService                ///         /// 动态调用web服务        ///         /// webservice url:http://xxx/zzz         /// className        /// methodName        /// the parameters used by methodName        /// 
type:object.Genanally,the result of the invoke operation
public static object InvokeWebService(string url, string className, string methodName, object[] args) { //string @namespace = "alarm.mobile.work.inter.bomc.boco.com"; string @namespace = GetNamespace(url); logger.Info(@namespace); if ((className == null) || (className == "")) { className = WebServiceHelper.GetWsClassName(url); logger.Info(className); } try { logger.Info(className); // 1. 使用 WebClient 下载 WSDL 信息。 WebClient wc = new WebClient(); //ServiceDescription类提供一种方法,以创建和格式化用于描述 XML Web services 的有效的 Web 服务描述语言 (WSDL) 文档文件,该文件是完整的,具有适当的命名空间、元素和特性。 无法继承此类。 //ServiceDescription.Read 方法 (Stream) 通过直接从 Stream实例加载 XML 来初始化ServiceDescription类的实例。 Stream stream = wc.OpenRead(url + "?WSDL"); // 2. 创建和格式化 WSDL 文档。 ServiceDescription sd = ServiceDescription.Read(stream); // 3. 创建客户端代理代理类。 //ServiceDescriptionImporter 类 公开一种为 XML Web services 生成客户端代理类的方法。 //ServiceDescriptionImporter.AddServiceDescription 方法 将指定的ServiceDescription添加到要导入的ServiceDescriptions值的集合中。 ServiceDescriptionImporter sdi = new ServiceDescriptionImporter(); sdi.ProtocolName = "soap"; sdi.AddServiceDescription(sd, "", ""); // 4. 使用 CodeDom 编译客户端代理类。 //CodeNamespace表示命名空间声明 CodeNamespace cn = new CodeNamespace(@namespace);// 为代理类添加命名空间,缺省为全局空间。 logger.Info(cn.Name); //生成客户端代理类代码 // CodeCompileUnit会提供一个CodeDOM程式圆形的容器,CodeCompileUnit含有一个集合, //可以储存含有CodeDOM原始程式码原形,专案参考的组件集合以及专案组件属性集合的CodeNamespace物件。 CodeCompileUnit ccu = new CodeCompileUnit(); ccu.Namespaces.Add(cn); sdi.Import(cn, ccu); // CSharpCodeProvider类提供存取C#程式码产生器和程式码编译器的执行个体。 CodeDomProvider provider = new CSharpCodeProvider(); //设定编译参数 //创建编译器的参数实例 CompilerParameters cplist = new 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"); //编译代理类 //CompilerResults表示从编译器返回的编译结果。使用指定的编译器设定, //根据CodeCompileUnit物件之指定阵列所包含的System.CodeDom树状结构,编译一个组件。 CompilerResults cr = provider.CompileAssemblyFromDom(cplist, ccu); //5. 使用 Reflection 调用 WebService 。 if (true == cr.Errors.HasErrors) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors) { sb.Append(ce.ToString()); sb.Append(System.Environment.NewLine); } logger.Error(sb.ToString()); //throw new Exception(sb.ToString()); } //生成代理实例,并调用方法 System.Reflection.Assembly assembly = cr.CompiledAssembly; // 如果在前面为代理类添加了命名空间,此处需要将命名空间添加到类型前面。 Type t = assembly.GetType(@namespace + "." + className, true, true); //Type t = assembly.GetType(className, true, true); // Activator类包含特定的方法,用以在本地或从远程创建对象类型,或获取对现有远程对象的引用。 //无法继承此类Activator.CreateInstance 方法 使用与指定参数匹配程度最高的构造函数创建指定类型的实例。 object obj = Activator.CreateInstance(t); //MethodInfo 的实例可以通过调用GetMethods或者Type对象或派生自Type的对象的GetMethod方法来获取, //还可以通过调用表示泛型方法定义的 MethodInfo 的MakeGenericMethod方法来获取。 System.Reflection.MethodInfo mi = t.GetMethod(methodName); logger.Info(mi.DeclaringType); return mi.Invoke(obj, args); } catch (Exception ex) { logger.Error(ex); //throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace)); return null; } } /// /// get the name of class name /// /// webservice url:http://xxx/zzz ///
private static string GetWsClassName(string wsUrl) { string[] parts = wsUrl.Split('/'); string[] pps = parts[parts.Length - 1].Split('.'); return pps[0]; } /// /// get the name of namespace /// /// webservice url:http://xxx/zzz ///
private static string GetNamespace(String URL) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL + "?WSDL"); SetWebRequest(request); WebResponse response = request.GetResponse(); StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8); XmlDocument doc = new XmlDocument(); doc.LoadXml(sr.ReadToEnd()); sr.Close(); string ns= doc.SelectSingleNode("//@targetNamespace").Value; return ns.Split('/')[ns.Split('/').Length - 1]; } private static void SetWebRequest(HttpWebRequest request) { request.Credentials = CredentialCache.DefaultCredentials; request.Timeout = 10000; } #endregion }
#region InvokeWebService        //动态调用web服务        public static object InvokeWebService(string url, string className, string methodName, object[] args)        {            string @namespace = GetNamespace(url);            logger.Info(@namespace);            if ((className == null) || (className == ""))            {                className = WebServiceHelper.GetWsClassName(url);                logger.Info(className);            }            try            {                logger.Info(className);                // 1. 使用 WebClient 下载 WSDL 信息。                           WebClient wc = new WebClient();                //ServiceDescription类提供一种方法,以创建和格式化用于描述 XML Web services 的有效的 Web 服务描述语言 (WSDL) 文档文件,该文件是完整的,具有适当的命名空间、元素和特性。 无法继承此类。                //ServiceDescription.Read 方法 (Stream) 通过直接从 Stream实例加载 XML 来初始化ServiceDescription类的实例。                Stream stream = wc.OpenRead(url + "?WSDL");                // 2. 创建和格式化 WSDL 文档。                ServiceDescription sd = ServiceDescription.Read(stream);                // 3. 创建客户端代理代理类。                //ServiceDescriptionImporter 类 公开一种为 XML Web services 生成客户端代理类的方法。                //ServiceDescriptionImporter.AddServiceDescription 方法 将指定的ServiceDescription添加到要导入的ServiceDescriptions值的集合中。                ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();                sdi.ProtocolName = "soap";                sdi.AddServiceDescription(sd, "", "");                // 4. 使用 CodeDom 编译客户端代理类。                //CodeNamespace表示命名空间声明                CodeNamespace cn = new CodeNamespace(@namespace);// 为代理类添加命名空间,缺省为全局空间。                logger.Info(cn.Name);                //生成客户端代理类代码                 // CodeCompileUnit会提供一个CodeDOM程式圆形的容器,CodeCompileUnit含有一个集合,                //可以储存含有CodeDOM原始程式码原形,专案参考的组件集合以及专案组件属性集合的CodeNamespace物件。                CodeCompileUnit ccu = new CodeCompileUnit();                ccu.Namespaces.Add(cn);                sdi.Import(cn, ccu);                // CSharpCodeProvider类提供存取C#程式码产生器和程式码编译器的执行个体。                CodeDomProvider provider = new CSharpCodeProvider();                //设定编译参数                  //创建编译器的参数实例                CompilerParameters cplist = new 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");                //编译代理类                          //CompilerResults表示从编译器返回的编译结果。使用指定的编译器设定,                //根据CodeCompileUnit物件之指定阵列所包含的System.CodeDom树状结构,编译一个组件。                CompilerResults cr = provider.CompileAssemblyFromDom(cplist, ccu);                //5. 使用 Reflection 调用 WebService 。                if (true == cr.Errors.HasErrors)                {                    System.Text.StringBuilder sb = new System.Text.StringBuilder();                    foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors)                    {                        sb.Append(ce.ToString());                        sb.Append(System.Environment.NewLine);                    }                    logger.Error(sb.ToString());                    //throw new Exception(sb.ToString());                }                //生成代理实例,并调用方法                             System.Reflection.Assembly assembly = cr.CompiledAssembly;                // 如果在前面为代理类添加了命名空间,此处需要将命名空间添加到类型前面。                Type t = assembly.GetType(@namespace + "." + className, true, true);                                //Type t = assembly.GetType(className, true, true);                // Activator类包含特定的方法,用以在本地或从远程创建对象类型,或获取对现有远程对象的引用。                //无法继承此类Activator.CreateInstance 方法  使用与指定参数匹配程度最高的构造函数创建指定类型的实例。                object obj = Activator.CreateInstance(t);                //MethodInfo 的实例可以通过调用GetMethods或者Type对象或派生自Type的对象的GetMethod方法来获取,                //还可以通过调用表示泛型方法定义的 MethodInfo 的MakeGenericMethod方法来获取。                System.Reflection.MethodInfo mi = t.GetMethod(methodName);                logger.Info(mi.DeclaringType);                return mi.Invoke(obj, args);            }            catch (Exception ex)            {                logger.Error(ex);                //throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace));                return null;            }        }        private static string GetWsClassName(string wsUrl)        {            string[] parts = wsUrl.Split('/');            string[] pps = parts[parts.Length - 1].Split('.');            return pps[0];        }        private static string GetNamespace(String URL)        {            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL + "?WSDL");            SetWebRequest(request);            WebResponse response = request.GetResponse();            StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);            XmlDocument doc = new XmlDocument();            doc.LoadXml(sr.ReadToEnd());            sr.Close();            string ns= doc.SelectSingleNode("//@targetNamespace").Value;            return ns.Split('/')[ns.Split('/').Length - 1];        }        private static void SetWebRequest(HttpWebRequest request)        {            request.Credentials = CredentialCache.DefaultCredentials;            request.Timeout = 10000;        }        #endregion

转载地址:http://qltga.baihongyu.com/

你可能感兴趣的文章
mybatis中的#和$的区别
查看>>
ubuntu下搭建NDK环境
查看>>
MessageDigest简单介绍
查看>>
webpack window 使用sass来编译css样式
查看>>
D3 & Data Visualization in Ext JS
查看>>
java通过UUID生成16位唯一订单号
查看>>
001-web基本程序搭建
查看>>
函数指针和指针函数
查看>>
借力AI 极验如何构建下一代业务安全?
查看>>
用Python制作迷宫GIF
查看>>
支付宝推出基于区块链跨境支付,巨头入场小企业将面临灭顶之灾
查看>>
从事互联网行业,怎样才能快速掌握一门编程语言呢?
查看>>
Redis 基础、高级特性与性能调优
查看>>
React native 第三方组件 React native swiper
查看>>
接口幂等设计
查看>>
编程入门指南
查看>>
移动端的自适应方案—REM
查看>>
你真的懂volatile吗
查看>>
Android 编译时注解-提升
查看>>
说说 Spring AOP 中 @Aspect 的高级用法
查看>>