我们都知道,调用WebService可以在工程中对WebService地址进行WEB引用,但是这确实很不方便。我想能够利用配置文件灵活调用WebService。如何实现呢?

用C#通过反射实现动态调用WebService

上代码,先试再说:

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 TestCommon
{
public class Webservice
{
/// <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 = "client";
try
{
//获取WSDL
WebClient wc = new WebClient();
Stream stream = wc.OpenRead(url + "?WSDL");
ServiceDescription sd = ServiceDescription.Read(stream);
string classname = sd.Services[0].Name;
ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
sdi.AddServiceDescription(sd, "", "");
CodeNamespace cn = new CodeNamespace(@namespace); //生成客户端代理类代码
CodeCompileUnit ccu = new CodeCompileUnit();
ccu.Namespaces.Add(cn);
sdi.Import(cn, ccu);
CSharpCodeProvider csc = new CSharpCodeProvider();
//ICodeCompiler icc = csc.CreateCompiler(); //设定编译参数
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 cr = csc.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, true, true);
object obj = Activator.CreateInstance(t);
System.Reflection.MethodInfo mi = t.GetMethod(methodname); return mi.Invoke(obj, args);
}
catch
{
return null;
}
}
}
}

注意:上述代码需要引用如下四个名称空间:
using System.Web.Services.Description;  //WS的描述
//以下几个用于根据描述动态生成代码并动态编译获取程序集
using System.CodeDom;  
using Microsoft.CSharp;
using System.CodeDom.Compiler;

如果你看到这段文字,说明您正使用RSS阅读或转自《一棵树-博客园》,原文地址:http://www.cnblogs.com/atree/p/WebService_dynamic.html

代码相对简单,为什么可以如此调用呢?动态编译后用反射来读取并执行。也许了解反射及如何反射对你会有帮助。

反射提供了封装程序集、模块和类型的对象(Type 类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。详细请查看:https://msdn.microsoft.com/zh-cn/library/ms173183(VS.80).aspx

为什么WebServices可以通过反射实现?

WebService在传输过程中是通过WSDL来进行描述的(使用SOAP协议)。因此,我们需要获取WebService的WSDL描述,并通过该描述来动态生成程序集。然后通过反射来获取新生成的程序集,并调用其方法!

以下是MSDN对其的描述:

XML Web services 的接口通常由 Web 服务描述语言 (WSDL) 文件来说明。例如,若要获取有关使用 http://localhost/service.asmx 处公开的 ASP.NET 的 Web 服务的 WSDL 说明,只需导航到 http://localhost/service.asmx?WSDL。使用 ServiceDescriptionImporter 类可以方便地将 WSDL 说明中包含的信息导入到System.CodeDom.CodeCompileUnit 对象。通过调整 Style 参数的值,可以指示 ServiceDescriptionImporter 实例生成客户端代理类(通过透明调用该类可提供 Web 服务的功能)或生成抽象类(该类封装 Web 服务的功能而不实现该功能)。如果将 Style 属性设置为 Client,则 ServiceDescriptionImporter 生成客户端代理类,通过调用这些类来提供说明的 Web 服务的功能。如果将 Style 属性设置为 Server,则 ServiceDescriptionImporter 实例生成抽象类,这些类表示所说明的 XML Web services 的功能而不进行实现。然后,可以通过编写从这些抽象类继承的类来对其进行实现,并实现相关的方法。

了解更多关于WebServices的知识:

C#调用WebService实例和开发

Web Service 的工作原理

MSDN:https://msdn.microsoft.com/zh-cn/library/system.web.services.webservice(VS.80).aspx

用C#通过反射实现动态调用WebService 告别Web引用的更多相关文章

  1. 用C#通过反射实现动态调用WebService 告别Web引用(转载)

    我们都知道,调用WebService可以在工程中对WebService地址进行WEB引用,但是这确实很不方便.我想能够利用配置文件灵活调用WebService.如何实现呢? 用C#通过反射实现动态调用 ...

  2. ASP.NET中WebService的创建和部署以及通过反射动态调用WebService

    一.在ASP.NET中创建WebService 首先我们先创建一个ASP.NET Web 应用程序,此处我们以VS2017为例 点击新创建的项目,右键添加新建项,选择Web服务,输入名称后点击添加 这 ...

  3. 动态调用WebService(C#) (非常实用)

    通常我们在程序中需要调用WebService时,都是通过“添加Web引用”,让VS.NET环境来为我们生成服务代理,然后调用对应的Web服务.这样是使工作简单了,但是却和提供Web服务的URL.方法名 ...

  4. C# .NET 动态调用webservice的三种方式

    转载自 百度文库 http://wenku.baidu.com/link?url=Q2q50wohf5W6UX44zqotXFEe_XOMaib4UtI3BigaNwipOHKNETloMF4ax4W ...

  5. WebService – 2.动态调用WebService

    在本节课程中,将演示如何通过程序动态添加.调用.编译.执行WebService并返回结果. WebService动态调用示意图 WebService相关知识 代码文档对象模型CodeDom的使用 编程 ...

  6. 动态调用WebService(C#)

    通常我们在程序中需要调用WebService时,都是通过“添加Web引用”,让VS.NET环境来为我们生成服务代理,然后调用对应的Web服务.这样是使工作简单了,但是却和提供Web服务的URL.方法名 ...

  7. Web Service学习笔记:动态调用WebService

    原文:Web Service学习笔记:动态调用WebService 多数时候我们通过 "添加 Web 引用..." 创建客户端代理类的方式调用WebService,但在某些情况下我 ...

  8. C# 动态调用 WebService (转)

    在 Visual Studio 中客户端程序可以添加服务引用来调用 WebService,这样 Visual Studio 会生成与之相关的代理类,通过这个代理类可以很方便的访问所需要的服务. 如果服 ...

  9. 动态调用WebService接口的几种方式

    一.什么是WebService? 这里就不再赘述了,想要了解的====>传送门 二.为什么要动态调用WebService接口? 一般在C#开发中调用webService服务中的接口都是通过引用过 ...

随机推荐

  1. poj3264 - Balanced Lineup(RMQ_ST)

    Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 45243   Accepted: 21240 ...

  2. 第六天:用javascript实现购彩拆分票的计算奖金

    需求如下: 购彩金额  拆分票数  <= 10    1票<= 100    10票<= 200   20票<= 500   50票<= 1000   100票 中奖金额 ...

  3. Windows2003 SQL2005解决系统Administrator密码不知道的问题

    Windows2003 SQL2005解决系统Administrator密码不知道的问题 今天上班的时候,有个同事说不知道谁设置了开机密码,那台电脑一直没有开机密码的他现在进不了桌面 那台电脑没有光驱 ...

  4. C#设计模式——单件模式

    一.为何需要单件模式 需求 我们开发了一个大型的项目,其中存在许多的工具类.但是其中很多的工具类我们并不是经常使用得到,甚至 一次都不会使用.但是这些工具类都是静态的类,会消耗很多的内存,即使一次都不 ...

  5. jqPlot图表插件学习之饼状图和环状图

    一.准备工作 官网下载(笔者选择的是jquery.jqplot.1.0.8r1250.zip这个版本) 然后读者需要根据自己的情况新建一个项目并且按照如下的方式加载对应的js和css(因为笔者在VS2 ...

  6. Http Status 参考

    http://tool.oschina.net/commons?type=5 状态码 含义 100 客户端应当继续发送请求.这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝.客户 ...

  7. jenkins2 Jenkinsfile

    推荐使用Jenkinsfile代替将groovy脚本直接写在jenkins job里. 文章来自:http://www.ciandcd.com文中的代码来自可以从github下载: https://g ...

  8. C#——Dictionary<TKey, TValue> 计算向量的余弦值

    说明:三角函数的余弦值Cos我想,每个学计算机的理工人都知道,但是真的明白它的用途,我也是刚明白.每个人在初中或者高中的时候,都有这么个疑惑,学三角函数干什么用的?很直白的答案就是考试用的.而且当时的 ...

  9. java web图片显示到浏览器

    今天研究了一下午,图片显示问题. jsp中获取绝对路径的方法:String contextPath = request.getContextPath();String path = request.g ...

  10. 重学JAVA基础(八):锁的基本知识

    1.线程状态 如上图,当我们新建一个线程,并start后,其实不一定会马上执行,因为只有操作系统调度了我们的线程,才能真正进行执行,而操作系统也随时可以运行其他线程,这时线程又回到可运行状态.这个过程 ...