学习C#中调用COM,后期绑定(以及对WinHttp COM对象的C#封装)-阿里云开发者社区

开发者社区> 开发与运维> 正文
登录阅读全文

学习C#中调用COM,后期绑定(以及对WinHttp COM对象的C#封装)

简介:
学习C#中调用COM,后期绑定全部代码 开始学习C#了,没打算从语法一点一点的看起!所以上来就直接开始代码了!同时也和Delphi之间的某些操作进行比较比较!于是想到了一个朋友用 Delphi写的通过ip138查询手机号码的例子,他用的是IdHttp来进行提交操作的。我在之前写飞信的控件的时候,用的http是Windows 自己内部的COM库:WinHttp.WinHttpRequest.5.1,这个玩意用起来还是相当方便的,于是就乘着学习,借机来在C#中动态创建这 个COM对象。要知道在Delphi中创建和调用一个COM对象,那是相当方便的。直接一个CreateOleObject就能创建一个COM对象了,然 后COM对象中的方法就能够直接通过这个东西直接调用。那么在C#中是否依然如此简洁?不晓得,是因为我刚接触还是咋地,折磨了半天,实在没摸索到简单的 方法来创建COM对象(当然,那种通过引用添加组件库到C#环境中去的方法不算,因为这个方法有一定的弊端,那便是当用户换了环境,重新来编译本程序的时 候,由于新的环境中可能并没有引用这个库,所以直接编译会出错,于是咱们又要重新添加引用一次本库!),唯一的办法就是后期绑定COM对象(至于是否有简 单方法,我不知道的,因为才学1天)。查阅了相关的一些资料之后得知,首先要通过COM对象名称获得这个对象在系统全局的一个ProgId,然后通过这个 ProgId获得这个对象的类型:

System.Type _ObjType = System.Type.GetTypeFromProgID(ComName);

然后通过这个类型来创建一个对象接口

object ComInstance= System.Activator.CreateInstance(_ObjType);       

之后,对该对象方法的调用都要通过type的InvokeMember方法来进行比如:

return ComType.InvokeMember(MethodName,System.Reflection.BindingFlags.InvokeMethod,null,ComInstance,args);

哎!写起来的代码量还真是有点大呢!于是,产生了一个想法,将这个COM对象后期绑定的玩意封装起来做一个公共的,能省多少代码就省多少代码,尽量的减少代码量:

复制代码
ExpandedBlockStart.gif代码
/*
 * Created by SharpDevelop.
 * User: Administrator
 * Date: 2009-12-2
 * Time: 23:26
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 
*/

using System;

namespace DxComOperate
{
    
/// <summary>
    
/// COM对象的后期绑定调用类库    
    
/// </summary>
    public class DxComObject
    {
        
private System.Type _ObjType;
        
private object ComInstance;
        
/*public DxComObject()
        {
            throw new
        }
*/
        
public DxComObject(string ComName)
        {
            
//根据COM对象的名称创建COM对象
            _ObjType = System.Type.GetTypeFromProgID(ComName);
            
if(_ObjType==null)
                
throw new Exception("指定的COM对象名称无效");
            ComInstance 
= System.Activator.CreateInstance(_ObjType);            
        }
        
public System.Type ComType
        {
            
get{return _ObjType;}
        }
        
//执行的函数
        public object DoMethod(string MethodName,object[] args)
        {
            
return ComType.InvokeMember(MethodName,System.Reflection.BindingFlags.InvokeMethod,null,ComInstance,args);
        }
        
//获得属性与设置属性
        public object this[string propName]
        {
            
get
            {
                
return _ObjType.InvokeMember( propName, System.Reflection.BindingFlags.GetProperty, null, ComInstance, null );
            }
            
set
            {                                
                _ObjType.InvokeMember( propName, System.Reflection.BindingFlags.SetProperty, 
null, ComInstance, new object[] {value} );
            }
        }            
    }
    
    
    
/// <summary>
    
/// WinHttp对象库
    
/// </summary>
    public class DxWinHttp
    {
        
private DxComObject HttpObj;
        
private string _ContentType;
        
public DxWinHttp()
        {
            
//构建WinHttp对象
            HttpObj = new DxComObject("WinHttp.WinHttpRequest.5.1");
        }
        
//设置Content-Type属性
        public string ContentType
        {
            
get{return _ContentType;}
            
set
            {
                
if (_ContentType.CompareTo(value)!=0)
                {
                    _ContentType 
= value;
                    
object[] args = new object[2];
                    args[
0= "Content-Type";args[1= value;
                    HttpObj.DoMethod(
"SetRequestHeader",args);
                }                                
            }
        }
        
        
    }
}
复制代码

 

代码写的也不复杂,就这么几句,但是我想应该看起来更加明亮化了。

比如,我现在通过这个封装操作库来通过ip138查询手机号码的归属地


 

复制代码
ExpandedBlockStart.gif代码
void Button1Click(object sender, EventArgs e)
        {
            
if (textBox1.Text.Length == 0)
            {
                MessageBox.Show(
"请输入一个手机号");
                
return;
            }
            DxComObject WinHttp 
= new DxComObject("WinHttp.WinHttpRequest.5.1");
            
string PostData = "http://www.ip138.com:8080/search.asp";    
            
object[] args = new object[3];//指定参数
            args[0= "GET";args[1= PostData;args[2= false;
            WinHttp.DoMethod(
"Open",args);//执行Open方法            
            PostData = "action=mobile&mobile="+this.textBox1.Text;    
            
            args 
= new object[2];
            args[
0= "Content-Length";args[1= PostData.Length;
            WinHttp.DoMethod(
"SetRequestHeader",args);
            
            args 
= new object[2];
            args[
0= "Content-Type";args[1= "application/x-www-form-urlencoded";
            WinHttp.DoMethod(
"SetRequestHeader",args);
            
            args 
= new object[2];
            args[
0= "User-Agent";args[1= "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
            WinHttp.DoMethod(
"SetRequestHeader",args);
            
            args 
= new object[1];
            args[
0= PostData;
            WinHttp.DoMethod(
"Send",args);
            
            DxComObject AdoStream 
= new DxComObject("Adodb.Stream");
            AdoStream[
"Type"= 1;
            AdoStream[
"Mode"= 3;
            
            args 
= new object[]{};
            AdoStream.DoMethod(
"Open",args);
            
            args 
= new object[1]{WinHttp["ResponseBody"]};
            AdoStream.DoMethod(
"Write",args);
            AdoStream[
"Position"= 0;
            AdoStream[
"Type"= 2;
            AdoStream[
"Charset"= "GB2312";
            
string Result = AdoStream["ReadText"].ToString();
            
            Info.mobileNo 
= GetReturnValue(DxValueType.DxPhone,Result);
            Info.City 
= GetReturnValue(DxValueType.DxPhoneCity,Result);            
            Info.CardType 
= GetReturnValue(DxValueType.DxCardType,Result);
            Info.CityCode 
= GetReturnValue(DxValueType.DxCityCode,Result);
            
this.propertyGrid1.Refresh();                        
        }
复制代码

//可见现在这个代码就已经很明显很明白了,但是写的代码量还是有些大,如果反复使用的话,就不爽了还是要写比较多的代码,于是开始着手对WinHttp这个COM对象进行封装


 

复制代码
ExpandedBlockStart.gif代码
/// <summary>
    
/// WinHttp对象库
    
/// </summary>
    public class DxWinHttp
    {
        
private DxComObject HttpObj;
        
private string _ContentType;
        
private int _ContentLength;
        
private bool _Active;
        
private System.Collections.ArrayList PostDataList;//提交的数据字段
        public DxWinHttp()
        {
            
//构建WinHttp对象
            HttpObj = new DxComObject("WinHttp.WinHttpRequest.5.1");            
            _ContentType 
= "application/x-www-form-urlencoded";
            _ContentLength 
= 0;    
            PostDataList 
= new System.Collections.ArrayList();
        }
        
        
//提交参数信息的个数
        public int PostDataCount
        {
            
get{return PostDataList.Count;}
        }
        
//设置Content-Type属性
        public string ContentType
        {
            
get{return _ContentType;}
            
set
            {
                
if(!_Active) _ContentType = value;
                
else if(_ContentType.CompareTo(value)!=0)
                {
                    _ContentType 
= value;
                    SetRequestHeader(
"Content-Type",_ContentType);
                }
            }
        }
        
        
//对象是否是打开状态
        public bool Active
        {
            
get{return _Active;}
        }
        
        
//设置Send数据的长度 
        public int ContentLength
        {
            
get{return _ContentLength;}
            
set
            {
                
if(!_Active) _ContentLength = value;
                
else if(_ContentLength != value)
                {
                    _ContentLength 
= value;
                    HttpObj.DoMethod(
"SetRequestHeader",new object[2]{"Content-Length",value});
                }
            }
        }
        
        
//执行之后返回的结果
        public string ResponseBody
        {
            
get
            {
                
if(_Active)
                {
                    DxComObject AdoStream 
= new DxComObject("Adodb.Stream");
                    AdoStream[
"Type"= 1;
                    AdoStream[
"Mode"= 3;
                    AdoStream.DoMethod(
"Open",new object[]{});
                    AdoStream.DoMethod(
"Write",new object[1]{HttpObj["ResponseBody"]});
                    AdoStream[
"Position"= 0;
                    AdoStream[
"Type"= 2;
                    AdoStream[
"Charset"= "GB2312";
                    
return AdoStream["ReadText"].ToString();
                }
                
else return "";
            }
        }
        
        
//设定请求头
        public string SetRequestHeader(string Header,object Value)
        {        
            
object obj;
            obj 
= HttpObj.DoMethod("SetRequestHeader",new object[]{Header,Value});
            
if(obj != nullreturn obj.ToString();
            
else return "True";
        }
        
        
//打开URL执行OpenMethod方法,Async指定是否采用异步方式调用,异步方式不会阻塞
        public string Open(string OpenMethod,string URL,bool Async)
        {
            
object obj;
            obj 
= HttpObj.DoMethod("Open",new object[]{OpenMethod,URL,Async});            
            
if (obj != null
            {
                _Active 
= false;
                
return obj.ToString();
            }
            
else
            {                
                SetRequestHeader(
"Content-Type",_ContentType);
                SetRequestHeader(
"User-Agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
                
if (_ContentLength != 0) SetRequestHeader("Content-Length",_ContentLength);                
                _Active 
= true;
                
return "True";
            }
        }            
        
        
//发送数据
        public string Send(string body)
        {
            
if(!_Active) return "False";
            
object obj;
            obj 
= HttpObj.DoMethod("Send",new object[1]{body});
            
if(obj != nullreturn obj.ToString();
            
else return "True";
        }
        
        
public void ClearPostData()
        {
            
this.PostDataList.Clear();
        }
        
//增加提交数据信息
        public void AddPostField(string FieldName,object Value)
        {
            
this.PostDataList.Add(FieldName+"="+Value.ToString());
        }
        
        
//通过参数指定提交
        public string DxPost()
        {
            
if(!_Active)
            {
                
return "False";
            }
            
string st="";
            
for(int i=0;i<this.PostDataList.Count;i++)
            {
                
if(st != "") st = st + "&"+ PostDataList[i].ToString();
                
else st = PostDataList[i].ToString();
            }
            
this.ContentLength = st.Length;
            
return Send(st);
        }
        
        
//设置等待超时等
        public string SetTimeouts(long ResolveTimeout,long ConnectTimeout,long SendTimeout,long ReceiveTimeout)
        {
            
object obj;
            obj 
= HttpObj.DoMethod("SetTimeouts",new object[4]{ResolveTimeout,ConnectTimeout,SendTimeout,ReceiveTimeout});
            
if(obj != nullreturn obj.ToString();
            
else return "True";
        }
        
//等待数据提交完成
        public string WaitForResponse(object Timeout,out bool Succeeded)
        {
            
if(!_Active) {Succeeded = false;return "";}
            
object obj;
            
bool succ;
            succ 
= false;
            System.Reflection.ParameterModifier[] ParamesM;
            ParamesM 
= new System.Reflection.ParameterModifier[1];
            ParamesM[
0= new System.Reflection.ParameterModifier (2); // 初始化为接口参数的个数
            ParamesM[0][1= true// 设置第二个参数为返回参数
            
            
//ParamesM[1] = true;
            object[] ParamArray = new object[2]{Timeout,succ};
            obj 
= HttpObj.DoMethod("WaitForResponse",ParamArray,ParamesM);
            System.Windows.Forms.MessageBox.Show(ParamArray[
1].ToString());
            Succeeded
=bool.Parse(ParamArray[1].ToString());
            
//Succeeded = bool.Parse(ParamArray[1].ToString);
            if(obj != null)    {return obj.ToString();}
            
else return "True";
        }
        
        
public string GetResponseHeader(string Header,ref string Value)
        {
            
if(!_Active) {Value="";return "";}
            
object obj;
            
/*string str;
            str = "";
            System.Reflection.ParameterModifier[] Parames;
            Parames = new System.Reflection.ParameterModifier[1];
            Parames[0] = new System.Reflection.ParameterModifier (2); // 初始化为接口参数的个数
            Parames[0][1] = true; 
*/// 设置第二个参数为返回参数
            obj = HttpObj.DoMethod("GetResponseHeader",new object[2]{Header,Value});
            
//Value = str;
            if(obj != null) {return obj.ToString();}
            
else return "True";
        }
    }
复制代码

封装完成,此时再看,用本库来查询手机归属地的代码:


 

复制代码
ExpandedBlockStart.gif代码
void Button2Click(object sender, EventArgs e)
        {
            
if (textBox1.Text.Length == 0)
            {
                MessageBox.Show(
"请输入一个手机号");
                
return;
            }            
            WinHttp.Open(
"GET","http://www.ip138.com:8080/search.asp",false);                
            WinHttp.ClearPostData();
            WinHttp.AddPostField(
"action","mobile");
            WinHttp.AddPostField(
"mobile",this.textBox1.Text);
            WinHttp.DxPost();
            
string Result = WinHttp.ResponseBody;
            Info.mobileNo 
= GetReturnValue(DxValueType.DxPhone,Result);
            Info.City 
= GetReturnValue(DxValueType.DxPhoneCity,Result);            
            Info.CardType 
= GetReturnValue(DxValueType.DxCardType,Result);
            Info.CityCode 
= GetReturnValue(DxValueType.DxCityCode,Result);
            
this.propertyGrid1.Refresh();    
        }
复制代码

现在的代码已经减少到了很多了!

 

下面给出完整的COM封装类库代码:


 

复制代码
ExpandedBlockStart.gif代码
/*
 * Created by SharpDevelop.
 * 作者: 不得闲
 * Date: 2009-12-2
 * Time: 23:26
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 
*/
using System;
namespace DxComOperate
{
    
/// <summary>
    
/// COM对象的后期绑定调用类库    
    
/// </summary>
    public class DxComObject
    {
        
private System.Type _ObjType;
        
private object ComInstance;
        
/*public DxComObject()
        {
            throw new
        }
*/
        
public DxComObject(string ComName)
        {
            
//根据COM对象的名称创建COM对象
            _ObjType = System.Type.GetTypeFromProgID(ComName);
            
if(_ObjType==null)
                
throw new Exception("指定的COM对象名称无效");
            ComInstance 
= System.Activator.CreateInstance(_ObjType);            
        }
        
public System.Type ComType
        {
            
get{return _ObjType;}
        }
        
//执行的函数
        public object DoMethod(string MethodName,object[] args)
        {
            
return ComType.InvokeMember(MethodName,System.Reflection.BindingFlags.InvokeMethod,null,ComInstance,args);
        }
        
        
public object DoMethod(string MethodName,object[] args,System.Reflection.ParameterModifier[] ParamMods)
        {            
            
return ComType.InvokeMember(MethodName,System.Reflection.BindingFlags.InvokeMethod,null,ComInstance,args,ParamMods,null,null);
        }
        
//获得属性与设置属性
        public object this[string propName]
        {
            
get
            {
                
return _ObjType.InvokeMember( propName, System.Reflection.BindingFlags.GetProperty, null, ComInstance, null );
            }
            
set
            {                                
                _ObjType.InvokeMember( propName, System.Reflection.BindingFlags.SetProperty, 
null, ComInstance, new object[] {value} );
            }
        }            
    }
    
    
    
/// <summary>
    
/// WinHttp对象库
    
/// </summary>
    public class DxWinHttp
    {
        
private DxComObject HttpObj;
        
private string _ContentType;
        
private int _ContentLength;
        
private bool _Active;
        
private System.Collections.ArrayList PostDataList;//提交的数据字段
        public DxWinHttp()
        {
            
//构建WinHttp对象
            HttpObj = new DxComObject("WinHttp.WinHttpRequest.5.1");            
            _ContentType 
= "application/x-www-form-urlencoded";
            _ContentLength 
= 0;    
            PostDataList 
= new System.Collections.ArrayList();
        }
        
        
//提交参数信息的个数
        public int PostDataCount
        {
            
get{return PostDataList.Count;}
        }
        
//设置Content-Type属性
        public string ContentType
        {
            
get{return _ContentType;}
            
set
            {
                
if(!_Active) _ContentType = value;
                
else if(_ContentType.CompareTo(value)!=0)
                {
                    _ContentType 
= value;
                    SetRequestHeader(
"Content-Type",_ContentType);
                }
            }
        }
        
        
//对象是否是打开状态
        public bool Active
        {
            
get{return _Active;}
        }
        
        
//设置Send数据的长度 
        public int ContentLength
        {
            
get{return _ContentLength;}
            
set
            {
                
if(!_Active) _ContentLength = value;
                
else if(_ContentLength != value)
                {
                    _ContentLength 
= value;
                    HttpObj.DoMethod(
"SetRequestHeader",new object[2]{"Content-Length",value});
                }
            }
        }
        
        
//执行之后返回的结果
        public string ResponseBody
        {
            
get
            {
                
if(_Active)
                {
                    DxComObject AdoStream 
= new DxComObject("Adodb.Stream");
                    AdoStream[
"Type"= 1;
                    AdoStream[
"Mode"= 3;
                    AdoStream.DoMethod(
"Open",new object[]{});
                    AdoStream.DoMethod(
"Write",new object[1]{HttpObj["ResponseBody"]});
                    AdoStream[
"Position"= 0;
                    AdoStream[
"Type"= 2;
                    AdoStream[
"Charset"= "GB2312";
                    
return AdoStream["ReadText"].ToString();
                }
                
else return "";
            }
        }
        
        
//设定请求头
        public string SetRequestHeader(string Header,object Value)
        {        
            
object obj;
            obj 
= HttpObj.DoMethod("SetRequestHeader",new object[]{Header,Value});
            
if(obj != nullreturn obj.ToString();
            
else return "True";
        }
        
        
//打开URL执行OpenMethod方法,Async指定是否采用异步方式调用,异步方式不会阻塞
        public string Open(string OpenMethod,string URL,bool Async)
        {
            
object obj;
            obj 
= HttpObj.DoMethod("Open",new object[]{OpenMethod,URL,Async});            
            
if (obj != null
            {
                _Active 
= false;
                
return obj.ToString();
            }
            
else
            {                
                SetRequestHeader(
"Content-Type",_ContentType);
                SetRequestHeader(
"User-Agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
                
if (_ContentLength != 0) SetRequestHeader("Content-Length",_ContentLength);                
                _Active 
= true;
                
return "True";
            }
        }            
        
        
//发送数据
        public string Send(string body)
        {
            
if(!_Active) return "False";
            
object obj;
            obj 
= HttpObj.DoMethod("Send",new object[1]{body});
            
if(obj != nullreturn obj.ToString();
            
else return "True";
        }
        
        
public void ClearPostData()
        {
            
this.PostDataList.Clear();
        }
        
//增加提交数据信息
        public void AddPostField(string FieldName,object Value)
        {
            
this.PostDataList.Add(FieldName+"="+Value.ToString());
        }
        
        
//通过参数指定提交
        public string DxPost()
        {
            
if(!_Active)
            {
                
return "False";
            }
            
string st="";
            
for(int i=0;i<this.PostDataList.Count;i++)
            {
                
if(st != "") st = st + "&"+ PostDataList[i].ToString();
                
else st = PostDataList[i].ToString();
            }
            
this.ContentLength = st.Length;
            
return Send(st);
        }
        
        
//设置等待超时等
        public string SetTimeouts(long ResolveTimeout,long ConnectTimeout,long SendTimeout,long ReceiveTimeout)
        {
            
object obj;
            obj 
= HttpObj.DoMethod("SetTimeouts",new object[4]{ResolveTimeout,ConnectTimeout,SendTimeout,ReceiveTimeout});
            
if(obj != nullreturn obj.ToString();
            
else return "True";
        }
        
//等待数据提交完成
        public string WaitForResponse(object Timeout,out bool Succeeded)
        {
            
if(!_Active) {Succeeded = false;return "";}
            
object obj;
            
bool succ;
            succ 
= false;
            System.Reflection.ParameterModifier[] ParamesM;
            ParamesM 
= new System.Reflection.ParameterModifier[1];
            ParamesM[
0= new System.Reflection.ParameterModifier (2); // 初始化为接口参数的个数
            ParamesM[0][1= true// 设置第二个参数为返回参数
            
            
//ParamesM[1] = true;
            object[] ParamArray = new object[2]{Timeout,succ};
            obj 
= HttpObj.DoMethod("WaitForResponse",ParamArray,ParamesM);
            System.Windows.Forms.MessageBox.Show(ParamArray[
1].ToString());
            Succeeded
=bool.Parse(ParamArray[1].ToString());
            
//Succeeded = bool.Parse(ParamArray[1].ToString);
            if(obj != null)    {return obj.ToString();}
            
else return "True";
        }
        
        
public string GetResponseHeader(string Header,ref string Value)
        {
            
if(!_Active) {Value="";return "";}
            
object obj;
            
/*string str;
            str = "";
            System.Reflection.ParameterModifier[] Parames;
            Parames = new System.Reflection.ParameterModifier[1];
            Parames[0] = new System.Reflection.ParameterModifier (2); // 初始化为接口参数的个数
            Parames[0][1] = true; 
*/// 设置第二个参数为返回参数
            obj = HttpObj.DoMethod("GetResponseHeader",new object[2]{Header,Value});
            
//Value = str;
            if(obj != null) {return obj.ToString();}
            
else return "True";
        }
    }
}
复制代码

这个对WinHttp的封装,还并不完全,只是封装了一部分的方法和属性,剩下的,如果又需要的人,可自行封装!

Ip138手机号码查询


本文转自 不得闲 博客园博客,原文链接: http://www.cnblogs.com/DxSoft/archive/2010/01/02/1637669.html ,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享: