动态调用webservices

2024-03-23 14:08
文章标签 动态 调用 webservices

本文主要是介绍动态调用webservices,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通常我们在程序中需要调用WebService时,都是通过“添加Web引用”,让VS.NET环境来为我们生成服务代理,然后调用对应的Web服务。这样是使工作简单了,但是却和提供Web服务的URL、方法名、参数绑定在一起了,这是VS.NET自动为我们生成Web服务代理的限制。如果哪一天发布Web服务的URL改变了,则我们需要重新让VS.NET生成代理,并重新编译。在某些情况下,这可能是不能忍受的,我们需要动态调用WebService的能力。比如我们可以把Web服务的URL保存在配置文件中,这样,当服务URL改变时,只需要修改配置文件就可以了。
     说了这么多,实际上我们要实现这样的功能:

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

     其中,url是Web服务的地址,methodname是要调用服务方法名,args是要调用Web服务所需的参数,返回值就是web服务返回的结果了。

     要实现这样的功能,你需要这几个方面的技能:反射、CodeDom、编程使用C#编译器、WebService。在了解这些知识后,就可以容易的实现web服务的动态调用了:

         #region InvokeWebService
        
// 动态调用web服务
         public static object InvokeWebService( string url, string methodname, object [] args)
         {
            
return WebServiceHelper.InvokeWebService(url , null ,methodname ,args) ;
         }

        
public static object InvokeWebService( string url,   string classname, string methodname, object [] args)
         {
            
string @namespace = " EnterpriseServerBase.WebService.DynamicWebCalling " ;
            
if ((classname == null ) || (classname == "" ))
             {
                 classname
= WebServiceHelper.GetWsClassName(url) ;
             }

            
try
             {
                
// 获取WSDL
                 WebClient wc                    = new WebClient();
                 Stream stream                  
= wc.OpenRead(url + " ?WSDL " );
                 ServiceDescription sd          
= ServiceDescription.Read(stream);
                 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 = 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, true , true );
                
object obj = Activator.CreateInstance(t);
                 System.Reflection.MethodInfo mi
= t.GetMethod(methodname);

                
return mi.Invoke(obj,args);
             }
            
catch (Exception ex)
             {
                
throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace));
             }
         }

        
private static string GetWsClassName( string wsUrl)
         {
            
string [] parts = wsUrl.Split( ' / ' ) ;
            
string [] pps    = parts[parts.Length - 1 ].Split( ' . ' ) ;

            
return pps[ 0 ] ;
         }
        
#endregion


     上面的注释已经很好的说明了各代码段的功能,下面给个例子看看,这个例子是通过访问http://www.webservicex.net/globalweather.asmx 服务来获取各大城市的天气状况。

             string url = " http://www.webservicex.net/globalweather.asmx " ;
            
string [] args = new string [ 2 ] ;
             args[
0 ] = this .textBox_CityName.Text ;
             args[
1 ] = " China " ;
            
object result = WebServiceHelper.InvokeWebService(url , " GetWeather " ,args) ;
            
this .label_Result.Text = result.ToString() ;


     上述的例子中,调用web服务使用了两个参数,第一个是城市的名字,第二个是国家的名字,Web服务返回的是XML文档,可以从其中解析出温度、风力等天气情况。
    
     最后说一下,C#虽然仍属于静态语言之列,但是其动态能力也是很强大的,不信,你可以看看Spring.net的AOP实现,这种“无侵入”的AOP实现比通常的.NET声明式AOP实现(一般是通过AOP Attribute)要漂亮的多。

这篇关于动态调用webservices的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/838533

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d

【LabVIEW学习篇 - 21】:DLL与API的调用

文章目录 DLL与API调用DLLAPIDLL的调用 DLL与API调用 LabVIEW虽然已经足够强大,但不同的语言在不同领域都有着自己的优势,为了强强联合,LabVIEW提供了强大的外部程序接口能力,包括DLL、CIN(C语言接口)、ActiveX、.NET、MATLAB等等。通过DLL可以使用户很方便地调用C、C++、C#、VB等编程语言写的程序以及windows自带的大

LeetCode:64. 最大正方形 动态规划 时间复杂度O(nm)

64. 最大正方形 题目链接 题目描述 给定一个由 0 和 1 组成的二维矩阵,找出只包含 1 的最大正方形,并返回其面积。 示例1: 输入: 1 0 1 0 01 0 1 1 11 1 1 1 11 0 0 1 0输出: 4 示例2: 输入: 0 1 1 0 01 1 1 1 11 1 1 1 11 1 1 1 1输出: 9 解题思路 这道题的思路是使用动态规划

string字符会调用new分配堆内存吗

gcc的string默认大小是32个字节,字符串小于等于15直接保存在栈上,超过之后才会使用new分配。

京东物流查询|开发者调用API接口实现

快递聚合查询的优势 1、高效整合多种快递信息。2、实时动态更新。3、自动化管理流程。 聚合国内外1500家快递公司的物流信息查询服务,使用API接口查询京东物流的便捷步骤,首先选择专业的数据平台的快递API接口:物流快递查询API接口-单号查询API - 探数数据 以下示例是参考的示例代码: import requestsurl = "http://api.tanshuapi.com/a

vue 父组件调用子组件的方法报错,“TypeError: Cannot read property ‘subDialogRef‘ of undefined“

vue 父组件调用子组件的方法报错,“TypeError: Cannot read property ‘subDialogRef’ of undefined” 最近用vue做的一个界面,引入了一个子组件,在父组件中调用子组件的方法时,报错提示: [Vue warn]: Error in v-on handler: “TypeError: Cannot read property ‘methods

vue2实践:el-table实现由用户自己控制行数的动态表格

需求 项目中需要提供一个动态表单,如图: 当我点击添加时,便添加一行;点击右边的删除时,便删除这一行。 至少要有一行数据,但是没有上限。 思路 这种每一行的数据固定,但是不定行数的,很容易想到使用el-table来实现,它可以循环读取:data所绑定的数组,来生成行数据,不同的是: 1、table里面的每一个cell,需要放置一个input来支持用户编辑。 2、最后一列放置两个b