The MSDN MethodBase.Invoke method in the pit

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

Module development summary: c# dynamic invocation of WebServices from the network and use the experience.

Msdn: MethodBase.Invoke method (Object, Object[]) method using the specified parameters or constructor represented by the current instance.

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

Parameters

obj

Object to invoke a method or constructor. If the method is static, this parameter is ignored. If the constructor is static, then this parameter must be a null reference (Visual Basic Nothing) instance or define the constructor of the class.

parameters

The parameter list of a method or constructor invocation. This is an array of objects , parameters of the object and the method or constructor to be invoked with the same number, order and type. If no parameters, the parameters should be a null reference (in the Visual Basic for Nothing).

If the method or constructor represented by this instance using the ref parameter (Visual Basic ByRef), the use of this function is called the method or constructor, this parameter does not require any special attributes. If the object in the array is not explicitly initialized with a value, then the object will contain the default value for that object type. For the elements of a reference type, the value is null (Visual Basic Nothing). For value type elements, the value is 0,0.0 or false, depending on the specific element type.

The return value

An object, including the return value method call, if the call is the constructor, or a null reference (in the Visual Basic for Nothing).

 

Xfire provides WebServices (see Baidu creation process, a lot of very good)

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#Call

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});//Error prone, abnormal alarm parameter number wrong

string methodNameString="invokedUseString"

object result2 = WebServiceHelper.InvokeWebService(webserviceUrl, null, methodNameString,argsArray);//Error prone, abnormal alarm parameter number wrong
Or

object result2 = WebServiceHelper.InvokeWebService(webserviceUrl, null, methodNameString,new object[]{title,desc});//Error prone, abnormal alarm parameter number wrong

 

Utility:

You need to add a reference: System.Web.Service

.net needs to be 4 framework client profile, we should change it to.Net 4 framework(VS2010)

Concrete steps:

1 from the target URL download WSDL data.

2 use ServiceDescription to create and format WSDL document file.

3 use ServiceDescriptionImporter to create a client proxy class.

4 using CodeDom to create dynamic client proxy class assembly.

5 using reflection called WebService method.

The specific code:

    class WebServiceHelper
    {


        #region InvokeWebService
        
        /// <summary>
        /// The dynamic invocation of Web Services
        /// </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 use WebClient to download the WSDL information.            
                WebClient wc = new WebClient();
                //The ServiceDescription class provides a method, in order to create and format for the description of the XML Web services effective Web service description language (WSDL) document file, the file is complete, with the appropriate namespace, element and characteristic. This class cannot be inherited. 
                //The ServiceDescription.Read method (Stream) through the case directly to initialize the ServiceDescription class from the Stream instance loading XML. 
                Stream stream = wc.OpenRead(url + "?WSDL");

                // 2 creating and formatting WSDL documents. 
                ServiceDescription sd = ServiceDescription.Read(stream);

                // 3 create a client proxy proxy class. 
                //The ServiceDescriptionImporter class provides a method for XML Web services to generate client proxy class. 
                //Set the ServiceDescriptionImporter.AddServiceDescription method adds the specified ServiceDescription to import the ServiceDescriptions value. 
                ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
                sdi.ProtocolName = "soap";
                sdi.AddServiceDescription(sd, "", "");
                // 4 use CodeDom to compile the client proxy classes. 
                //CodeNamespace said the namespace declaration
                CodeNamespace cn = new CodeNamespace(@namespace);// Add a namespace for the proxy class, the default is the global space. 
                logger.Info(cn.Name);
                //To generate client proxy code 
                // CodeCompileUnit provides a CodeDOM program to circular container, CodeCompileUnit contains a collection of, 
                //Can be stored with CodeDOM source code form, project reference set of components and assembly attributes of CodeNamespace objects. 
                CodeCompileUnit ccu = new CodeCompileUnit();
                ccu.Namespaces.Add(cn);
                sdi.Import(cn, ccu);
                // The CSharpCodeProvider class provides access to the C# code generator and code the compiler to perform individual. 
                CodeDomProvider provider = new CSharpCodeProvider();

                //Set the compile parameters  
                //Parameters to create an instance of the compiler
                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");
                //Compile the proxy class          
                //CompilerResults said the results returned from the compiler compiler. Using the specified compiler settings, 
                //System.CodeDom tree structure according to the specified array of CodeCompileUnit objects contain, the compilation of a component. 
                CompilerResults cr = provider.CompileAssemblyFromDom(cplist, ccu);
                //5 using Reflection to call 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());
                }
                //The generated proxy instance, and call the method             
                System.Reflection.Assembly assembly = cr.CompiledAssembly;
                // If in front for the proxy class to add namespaces, here need to be added to the front of the namespace type. 
                Type t = assembly.GetType(@namespace + "." + className, true, true);
                
                //Type t = assembly.GetType(className, true, true);
                // The Activator class contains a specific method, is used to locally or from a remote object creation type, or get a reference to the remote object. 
                //No inheritance creates an instance of the specified type using the Activator.CreateInstance method with the specified parameters matching the highest degree of constructor. 
                object obj = Activator.CreateInstance(t);
                //An instance of MethodInfo could be obtained by calling GetMethods or Type object or derived from the Type object's GetMethod method, 
                //Also can be obtained by calling the MakeGenericMethod method of a generic method definition MethodInfo. 
                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
        //The dynamic invocation of Web Services
        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 use WebClient to download the WSDL information.            
                WebClient wc = new WebClient();
                //The ServiceDescription class provides a method, in order to create and format for the description of the XML Web services effective Web service description language (WSDL) document file, the file is complete, with the appropriate namespace, element and characteristic. This class cannot be inherited. 
                //The ServiceDescription.Read method (Stream) through the case directly to initialize the ServiceDescription class from the Stream instance loading XML. 
                Stream stream = wc.OpenRead(url + "?WSDL");

                // 2 creating and formatting WSDL documents. 
                ServiceDescription sd = ServiceDescription.Read(stream);

                // 3 create a client proxy proxy class. 
                //The ServiceDescriptionImporter class provides a method for XML Web services to generate client proxy class. 
                //Set the ServiceDescriptionImporter.AddServiceDescription method adds the specified ServiceDescription to import the ServiceDescriptions value. 
                ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
                sdi.ProtocolName = "soap";
                sdi.AddServiceDescription(sd, "", "");
                // 4 use CodeDom to compile the client proxy classes. 
                //CodeNamespace said the namespace declaration
                CodeNamespace cn = new CodeNamespace(@namespace);// Add a namespace for the proxy class, the default is the global space. 
                logger.Info(cn.Name);
                //To generate client proxy code 
                // CodeCompileUnit provides a CodeDOM program to circular container, CodeCompileUnit contains a collection of, 
                //Can be stored with CodeDOM source code form, project reference set of components and assembly attributes of CodeNamespace objects. 
                CodeCompileUnit ccu = new CodeCompileUnit();
                ccu.Namespaces.Add(cn);
                sdi.Import(cn, ccu);
                // The CSharpCodeProvider class provides access to the C# code generator and code the compiler to perform individual. 
                CodeDomProvider provider = new CSharpCodeProvider();

                //Set the compile parameters  
                //Parameters to create an instance of the compiler
                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");
                //Compile the proxy class          
                //CompilerResults said the results returned from the compiler compiler. Using the specified compiler settings, 
                //System.CodeDom tree structure according to the specified array of CodeCompileUnit objects contain, the compilation of a component. 
                CompilerResults cr = provider.CompileAssemblyFromDom(cplist, ccu);
                //5 using Reflection to call 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());
                }
                //The generated proxy instance, and call the method             
                System.Reflection.Assembly assembly = cr.CompiledAssembly;
                // If in front for the proxy class to add namespaces, here need to be added to the front of the namespace type. 
                Type t = assembly.GetType(@namespace + "." + className, true, true);
                
                //Type t = assembly.GetType(className, true, true);
                // The Activator class contains a specific method, is used to locally or from a remote object creation type, or get a reference to the remote object. 
                //No inheritance creates an instance of the specified type using the Activator.CreateInstance method with the specified parameters matching the highest degree of constructor. 
                object obj = Activator.CreateInstance(t);
                //An instance of MethodInfo could be obtained by calling GetMethods or Type object or derived from the Type object's GetMethod method, 
                //Also can be obtained by calling the MakeGenericMethod method of a generic method definition MethodInfo. 
                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
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Meredith at November 17, 2013 - 1:46 PM