Web Service相信大家都很熟悉,当多个系统间的交互非常频繁的时候,开发过程中总是需要对web service进行测试,确保web service能正常运行。常用的方法是输入web service地址进行测试,但是webservice经常会部署在其他的机器上,不能进行直接测试,只能通过编写测试代码进行测试了,这样感觉非常繁琐。这里我们可以通过动态调用web service来进行测试。

动态调用web service方法

public static object InvokeWebService(string url, string methodname, object[] args)
        
{
            
try
            
{
                
string @namespace = "WebService.DynamicWebCalling";
                
string[] parts = url.Split('/');
                
string[] pps = parts[parts.Length - 1].Split('.');
                
string classname = pps[0];
                System.Net.WebClient wc 
= new System.Net.WebClient();
                System.IO.Stream 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);
                
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);
                    }

                    
throw new Exception(sb.ToString());
                }

                System.Reflection.Assembly assembly 
= cr.CompiledAssembly;
                Type t 
= assembly.GetType(@namespace + "." + classname, truetrue);
                
object obj = Activator.CreateInstance(t);
                System.Reflection.MethodInfo mi 
= t.GetMethod(methodname);
                
return mi.Invoke(obj, args);
            }

            
catch (Exception ex)
            
{
                
throw ex;
            }

        }


程序运行界面



源代码下载
/Files/binbin1845/WSTest.rar

#2楼  2008-02-21 17:01 | 双鱼座      

呵呵,又见动态Web Service客户端。
你的方案是仿照手工过程,用类似WSDL.EXE工具的方式,并通过CodeDom动态编译。这种方式最简单(System.Web.Service只提供了CodeDom方式),但也最让人不爽。
前段时间我写过一个改良的版本,只用System.Web.Service的WSDL解析部分,然后用Emit生成代码。这样有一个好处,在获得WSDL的URL后,在调用前(生成动态代码前)可以列出所有的方法,并自动显示这些方法的参数类型。
其实,最简单的方法还是用MSOSOAP30.DLL。.net clr很好地解决了IDispatch接口及晚绑定的问题,所以用这个进程内服务器效果非常好。只需要四行代码:
Type objType = Type.GetTypeFromProgID("MSOSOAP.SoapClient30");
object obj = Activator.CreateInstance(objType);
obj.InvokeMember("MSSoapInit", 0, nil, new object[] { WsdlUrl });
return obj.InvokeMember("方法名", 0, nil, new object[] { "参数" });