zoukankan      html  css  js  c++  java
  • msdn 中MethodBase.Invoke 方法 介绍中的坑

    模块开发总结:
    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+"	"+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
            
            /// <summary>
            /// 动态调用web服务
            /// </summary>
            /// <param name="url">webservice url:http://xxx/zzz </param>
            /// <param name="className">className</param>
            /// <param name="methodName">methodName</param>
            /// <param name="args">the parameters used by methodName</param>
            /// <returns>type:object.Genanally,the result of the invoke operation</returns>
            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;
                }
            }
            /// <summary>
            /// get the name of class name
            /// </summary>
            /// <param name="wsUrl">webservice url:http://xxx/zzz </param>
            /// <returns></returns>
            private static string GetWsClassName(string wsUrl)
            {
                string[] parts = wsUrl.Split('/');
                string[] pps = parts[parts.Length - 1].Split('.');
                return pps[0];
            }
            
            /// <summary>
            /// get the name of  namespace
            /// </summary>
            /// <param name="URL">webservice url:http://xxx/zzz </param>
            /// <returns></returns>
            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
  • 相关阅读:
    关于c#中的委托和事件
    Unity3d中默认函数调用顺序(MonoBehaviour)
    u3d 摄像机详解
    u3d中的坐标系
    u3d中的向量 vector3 vector2
    u3d中的INput
    C#构造函数
    解析C#中[],List,Array,ArrayList的区别及应用
    Mybatis(七) mybatis的逆向工程的配置详解
    Mybatis(六) Spring整合mybatis
  • 原文地址:https://www.cnblogs.com/softidea/p/3241135.html
Copyright © 2011-2022 走看看