分享
 
 
 

用C#创建COM对象

王朝c#·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

在本篇文章中,我们将讨论下面的问题:

·使用C#创建一个简单的COM对象(使用COM的Interop特性)。

·从VC++客户端软件中访问COM。客户端软件使用了TypeLibrary(.TLB文件)。

为了简单和方便开发人员使用、测试起见,我们使用了SQLSERVER数据库软件的缺省安装中的Northwind数据库。

·修改COM对象中SQLServer的名字,与SQLServer连接。

·我们已经创建了连接数据库用的分别为scott、tiger的用户名和口令,我们可以使用它或者其他现有的用户名和口令。

第一部分:用C#创建简单的COM对象

COM对象是ClassLibrary类,它生成DLL文件。要在VS开发环境中创建一个简单的COM对象,我们可以依次选择“文件”->;“新创建”->;“工程”->;“VisualC#工程”->;“类库”,然后创建一个名字为Database_COMObject的工程。

需要注意的是:在COM中调用VC#对象需要下面的条件:

·类必须是public性质。

·特性、方法和事件必须是public性质的。

·特性和方法必须在类接口中定义。

·事件必须在事件接口中定义。

不是在这些接口中定义的public性质的类成员不能被COM访问,但它们可以被其他的.NET Framework对象访问。要让COM能够访问特性和方法,我们必须在类接口中定义它们,使它们具有DispId属性,并在类中实现这些特性和方法。这些成员定义时的顺序也就是它们在COM中顺序。要让COM访问类中的事件,必须在事件接口中定义这些事件,并赋予它们DispId属性。事件接口不应当由类完成,类只实现类接口(它可以实现不止一个接口,但第一个接口是缺省接口),应当在缺省接口中实现需要让COM访问的方法和特性,方法和特性必须被标识为public性质,并符合在类接口中的定义。需要让COM访问的事件也在缺省的类接口中完成,它们也必须被标识为public性质,并符合事件接口中的定义。

在接口名字之前,每个接口需要一个GUID特性。要生成变个唯一的Guid,需要运行guidgen.exe工具软件,并选择“注册表格式” 下面是一个类界面:

[Guid(";694C1820-04B6-4988-928F-FD858B95C880";)]

public interface DBCOM_Interface

{

[DispId(1)]

void Init(string userid , string password);

[DispId(2)]

bool ExecuteSelectCommand(string selCommand);

[DispId(3)]

bool NextRow();

[DispId(4)]

void ExecuteNonSelectCommand(string insCommand);

[DispId(5)]

string GetColumnData(int pos);

}

COM事件接口: // 事件接口Database_COMObjectEvents

[Guid(";47C976E0-C208-4740-AC42-41212D3C34F0";),

InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]

public interface DBCOM_Events

{

}

下面是实际的类定义:

[Guid(";9E5E5FB2-219D-4ee7-AB27-E4DBED8E123E";),

ClassInterface(ClassInterfaceType.None),

ComSourceInterfaces(typeof(DBCOM_Events))]

public class DBCOM_Class : DBCOM_Interface

{

需要注意的是,在类的前面,需要设置下面的特性:

ClassInterface(ClassInterfaceType.None),

ComSourceInterfaces(typeof(DBCOM_Events))]

ClassInterfaceType.None表示没有为该类生成类接口,如果没有明确地实现接口,类只能通过IDispatch提供后期绑定访问。用户希望通过明确地由类实现的接口使外部对象能够访问类的功能,这也是推荐的ClassInterfaceAttribute的设置。

ComSourceInterfaces(typeof(DBCOM_Events))]确定许多作为COM事件向外部对象提供的接口。在本文的例子中,我们不对外部对象开放任何事件。

下面是COM对象完整的源代码:

using System;

using System.Runtime.InteropServices;

using System.IO;

using System.Text;

using System.Data.SqlClient;

using System.Windows.Forms ;

namespace Database_COMObject

{

[Guid(";694C1820-04B6-4988-928F-FD858B95C880";)]

public interface DBCOM_Interface

{

[DispId(1)]

void Init(string userid , string password);

[DispId(2)]

bool ExecuteSelectCommand(string selCommand);

[DispId(3)]

bool NextRow();

[DispId(4)]

void ExecuteNonSelectCommand(string insCommand);

[DispId(5)]

string GetColumnData(int pos);

}

// 事件接口Database_COMObjectEvents

[Guid(";47C976E0-C208-4740-AC42-41212D3C34F0";),

InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]

public interface DBCOM_Events

{

}

[Guid(";9E5E5FB2-219D-4ee7-AB27-E4DBED8E123E";),

ClassInterface(ClassInterfaceType.None),

ComSourceInterfaces(typeof(DBCOM_Events))]

public class DBCOM_Class : DBCOM_Interface

{

private SqlConnection myConnection = null ;

SqlDataReader myReader = null ;

public DBCOM_Class()

{

}

public void Init(string userid , string password)

{

try

{

string myConnectString = ";user id=";+userid+";;password=";+password+

";;Database=NorthWind;Server=SKYWALKER;Connect Timeout=30";;

myConnection = new SqlConnection(myConnectString);

myConnection.Open();

MessageBox.Show(";CONNECTED";);

}

catch(Exception e)

{

MessageBox.Show(e.Message);

}

}

public bool ExecuteSelectCommand(string selCommand)

{

if ( myReader != null )

myReader.Close() ;

SqlCommand myCommand = new SqlCommand(selCommand);

myCommand.Connection = myConnection;

myCommand.ExecuteNonQuery();

myReader = myCommand.ExecuteReader();

return true ;

}

public bool NextRow()

{

if ( ! myReader.Read() )

{

myReader.Close();

return false ;

}

return true ;

}

public string GetColumnData(int pos)

{

Object obj = myReader.GetValue(pos);

if ( obj == null ) return ";"; ;

return obj.ToString() ;

}

public void ExecuteNonSelectCommand(string insCommand)

{

SqlCommand myCommand = new SqlCommand(insCommand , myConnection);

int retRows = myCommand.ExecuteNonQuery();

}

}

}

在创建COM对象前,我们必须向COM Interop注册该对象。右击方案管理器中的工程名字,点击快捷菜单上的“属性”选项,然后再点击“配置”->;“创建”,扩展output小节,将Register for COM Interop选项的值设置为true。这样,一个COM对象就能够与可管理性应用程序进行交互。

为了使COM对象能够被外部对象调用,类库组合必须有一个强名字。创建强名字需要用到SN.EXE名字: sn -k Database_COM_Key.snk

打开AssemblyInfo.cs,并修改下面一行的内容:

[assembly: AssemblyKeyFile(";Database_COM_Key.snk";)]

创建对象。创建对象会生成一个可以被导入到可管理性或非可管理性代码中的类库。

第二部分:使用Visual C++创建访问COM对象的客户端软件

·使用VC++开发环境创建一个简单的工程。

·使用#import directive导入类型库。

·在界面中创建一个Smart Pointer,从接口中执行COM类提供的功能。确保在应用程序加载时添加CoInitialize()调用: CoInitialize(NULL);

Database_COMObject::DBCOM_InterfacePtr p(__uuidof(Database_COMObject::DBCOM_Class));

db_com_ptr = p ;

db_com_ptr->;Init(";scott"; , ";tiger";);

下面的代码对Customers数据库表执行一个SQL命令,返回给定ID的客户的信息:

char cmd[1024];

sprintf(cmd , ";SELECT COMPANYNAME , CONTACTNAME ,

CONTACTTITLE , ADDRESS FROM CUSTOMERS WHERE CUSTOMERID = '%s'"; , m_id );

const char *p ;

bool ret = db_com_ptr->;ExecuteSelectCommand(cmd);

if ( ! db_com_ptr->;NextRow() ) return ;

_bstr_t mData = db_com_ptr->;GetColumnData(3);

p = mData ;

m_address = (CString)p ;

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有