c#中动态编译wsdl并调用接口

由于工作中需要,接触到了编译wsdl。

 

首先,说下手动情况下使用wsdl:

 

1)使用浏览器打开webService页面。如:http://192.168.1.5:8080/Service.axms?wsdl

2)使用页面另存功能,将当前页面保存为Service.wsdl文件。

3)使用管理员权限打开 VS开发人员命令提示,

输入命令 wsdl  Service.wsdl文件全路径  /out: 将要生成的cs文件的全路径

如:wsdl c:\\...\\Service.wsdl /out: c:\\...\\Service.cs

该命令将在out所指定的路径下生成.cs文件,.cs文件中的内容就为webService页面源文件的代理类。

4)在c#项目中--添加现有项--该.cs文件--引入System.Web.Serivce,使用该.cs文件中的方法,即可调用webService页面中同名接口,并向WebService传递数据。

 

其次,说下动态编译wsdl:

直接上代码吧

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Web.Services.Description;
using System.CodeDom;
using Microsoft.CSharp;
using System.CodeDom.Compiler;

namespace WebserviceCallingTest
{
class WebserviceCalling
{
/// <summary>
/// 实例化WebServices
/// </summary>
/// <param name="url">WebServices地址</param>
/// <param name="methodname">调用的方法</param>
/// <param name="args">把webservices里需要的参数按顺序放到这个object[]里</param>

public static object InvokeWebService(string url, string methodname, object[] args)
{

//这里的namespace是需引用的webservices的命名空间,也可以加一个参数从外面传进来。
string @namespace = "MyWebserviceTest";
Console.WriteLine("定义命名空间:" + @namespace);
try
{
Console.WriteLine("开始获取wsdl...");
//获取WSDL
WebClient wc = new WebClient();
Console.WriteLine("开始获取流数据...");
Stream stream = wc.OpenRead(url + "?wsdl");

ServiceDescription sd = ServiceDescription.Read(stream);
Console.WriteLine("格式化流数据...");
string classname = sd.Services[0].Name;
Console.WriteLine("获取包含在流中的service集合中service[0].name:" + classname);
ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
Console.WriteLine("建立生成代理类功能类对象的实例...");
sdi.AddServiceDescription(sd, "", "");
/*
* sdi.ProtocolName = "SOAP";
* 这里说明下,协议类型有很多种,主要是 SOAP 和 SOAP12
* 如果这里不配置,可能会出现两种异常:
* 1. XML文档中< X,X >有错误
* 2. 命名空间 http://xxxxx/xxxx 无法导入到 xxxxxxxx 中。
*
* 另:如果配置了某一值,则只能使用这个值所代表的协议类型
* 建议:可以使用参数来传递协议类型。
*/
sdi.ProtocolName = "SOAP";
Console.WriteLine("配置访问XML的协议为:" + sdi.ProtocolName );
Console.WriteLine("将流数据加入实例中...");
CodeNamespace cn = new CodeNamespace(@namespace);
Console.WriteLine("生成命名空间对象...");


//生成客户端代理类代码
CodeCompileUnit ccu = new CodeCompileUnit();
Console.WriteLine("建立CodeDom容器对象...");
ccu.Namespaces.Add(cn);
Console.WriteLine("为容器添加命名空间...");
sdi.Import(cn, ccu);
Console.WriteLine("将命名空间和容器导入wsdl流中...");
CSharpCodeProvider csc = new CSharpCodeProvider();
Console.WriteLine("建立C#代码生成器和编译器对象...");
//ICodeCompiler icc = csc.CreateCompiler();
//设定编译参数
CompilerParameters cplist = new CompilerParameters();
Console.WriteLine("设置编译参数...");
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");
//这里的字段OutputAssembly可配置也可不配置,配置后下面的编译器对象将按照配置的路径将wsdl生成.dll文件
cplist.OutputAssembly = System.IO.Directory.GetCurrentDirectory() + "\\" + classname + ".dll";
Console.WriteLine("根据编译器对象按照编译参数对象和容器对象设置编译生成代理类对象...");
//编译代理类
CompilerResults cr = csc.CompileAssemblyFromDom(cplist, ccu);

Console.WriteLine("编译完成...");
Console.WriteLine("检测编译是否产生错误...");
if (File.Exists(System.IO.Directory.GetCurrentDirectory() + "\\" + classname + ".dll"))
{
Console.WriteLine(classname + ".dll" + "文件生成...");
}
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());
}

Console.WriteLine("开始调用编译完的程序集...");
//生成代理实例,并调用方法
/*
* 这里使用 System.Reflection.Assembly assembly = cr.CompiledAssembly 其实并不保险,assembly默认调用的是当前的程序集,
* 也就是默认调用的是WebserviceCalling(执行动态编译wsdl的程序集,就是本文),而不是编译成功的 Service.dll
* 所以,当执行assembly.GetType(@namespace + "." + classname, true, true)时,得到的 Type t 为null。
*/
Console.WriteLine("建立程序集对象...");
//System.Reflection.Assembly assembly = cr.CompiledAssembly;
/*
* 借用大神http://www.cnblogs.com/keyyang/p/3803920.html的解决办法
* 先加载 Service.dll
* Assembly asmb = Assembly.LoadFrom(classname + ".dll") ;
* 再获取程序集中的类型对象
* Type supType = asmb.GetType(@namespace + "." + classname) ;
*/

System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(classname + ".dll");
Type t = assembly.GetType(@namespace + "." + classname, true, true);
Console.WriteLine("获取程序集中" + @namespace + "." + classname + "中的类型对象...");
object obj = Activator.CreateInstance(t);
Console.WriteLine("建立该对象实例...");
System.Reflection.MethodInfo mi = t.GetMethod(methodname);
Console.WriteLine("获取名为" + methodname + "的方法的信息....\n" + mi.ToString());
Console.WriteLine("开始调用该方法...");
return mi.Invoke(obj, args);
}
catch
{
return null;
}
}
static void Main(string[] args)
{
String url = "http://192.168.5.140:8090/Service1.asmx" ;
String methodname = "Add" ;
String param = "1,2" ;
Console.WriteLine("调用方法:" + methodname + ",传递参数:" + param.ToString());
Console.WriteLine("得到结果:" + InvokeWebService(url, methodname, param.Split(',')).ToString());
Console.ReadLine();
}
}
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值