影音先锋男人资源av站_狠狠色综合激情丁香五月_爱爱爱爱看视频_在线播放免费人成视频在线观看_少妇人妻综合久久中文字幕_国产午夜无码精品免费看_久久久久久夜精品精品免费啦_男人女人午夜视频免费_日本xxxx裸体xxxx_丰满人妻熟妇乱又仑精品

電子科大論壇-非清水河畔

標(biāo)題: 用C#創(chuàng)建COM對(duì)象 [打印本頁(yè)]

作者: songlai    時(shí)間: 2007-11-29 17:32
標(biāo)題: 用C#創(chuàng)建COM對(duì)象
在本篇文章中,我們將討論下面的問題:

·使用C#創(chuàng)建一個(gè)簡(jiǎn)單的COM對(duì)象(使用COM的Interop特性)。

·從VC++客戶端軟件中訪問COM。客戶端軟件使用了TypeLibrary(.TLB文件)。為了簡(jiǎn)單和方便開發(fā)人員使用、測(cè)試起見,我們使用了SQLSERVER數(shù)據(jù)庫(kù)軟件的缺省安裝中的Northwind數(shù)據(jù)庫(kù)。

·修改COM對(duì)象中SQLServer的名字,與SQLServer連接。

·我們已經(jīng)創(chuàng)建了連接數(shù)據(jù)庫(kù)用的分別為scott、tiger的用戶名和口令,我們可以使用它或者其他現(xiàn)有的用戶名和口令。

第一部分:用C#創(chuàng)建簡(jiǎn)單的COM對(duì)象

  COM對(duì)象是ClassLibrary類,它生成DLL文件。要在VS開發(fā)環(huán)境中創(chuàng)建一個(gè)簡(jiǎn)單的COM對(duì)象,我們可以依次選擇“文件”->“新創(chuàng)建”->“工程”->“VisualC#工程”->“類庫(kù)”,然后創(chuàng)建一個(gè)名字為Database_COMObject的工程。
  需要注意的是:在COM中調(diào)用VC#對(duì)象需要下面的條件:

·類必須是public性質(zhì)。

·特性、方法和事件必須是public性質(zhì)的。

·特性和方法必須在類接口中定義。

·事件必須在事件接口中定義。

  不是在這些接口中定義的public性質(zhì)的類成員不能被COM訪問,但它們可以被其他的.NET Framework對(duì)象訪問。要讓COM能夠訪問特性和方法,我們必須在類接口中定義它們,使它們具有DispId屬性,并在類中實(shí)現(xiàn)這些特性和方法。這些成員定義時(shí)的順序也就是它們?cè)贑OM中順序。要讓COM訪問類中的事件,必須在事件接口中定義這些事件,并賦予它們DispId屬性。事件接口不應(yīng)當(dāng)由類完成,類只實(shí)現(xiàn)類接口(它可以實(shí)現(xiàn)不止一個(gè)接口,但第一個(gè)接口是缺省接口),應(yīng)當(dāng)在缺省接口中實(shí)現(xiàn)需要讓COM訪問的方法和特性,方法和特性必須被標(biāo)識(shí)為public性質(zhì),并符合在類接口中的定義。需要讓COM訪問的事件也在缺省的類接口中完成,它們也必須被標(biāo)識(shí)為public性質(zhì),并符合事件接口中的定義。
  在接口名字之前,每個(gè)接口需要一個(gè)GUID特性。要生成變個(gè)唯一的Guid,需要運(yùn)行g(shù)uidgen.exe工具軟件,并選擇“注冊(cè)表格式”。

下面是一個(gè)類界面:

[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
{
}


下面是實(shí)際的類定義:
[Guid("9E5E5FB2-219D-4ee7-AB27-E4DBED8E123E"),
ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(DBCOM_Events))]
public class DBCOM_Class : DBCOM_Interface
{


需要注意的是,在類的前面,需要設(shè)置下面的特性:
ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(DBCOM_Events))]

  ClassInterfaceType.None表示沒有為該類生成類接口,如果沒有明確地實(shí)現(xiàn)接口,類只能通過(guò)IDispatch提供后期綁定訪問。用戶希望通過(guò)明確地由類實(shí)現(xiàn)的接口使外部對(duì)象能夠訪問類的功能,這也是推薦的ClassInterfaceAttribute的設(shè)置。

  ComSourceInterfaces(typeof(DBCOM_Events))]確定許多作為COM事件向外部對(duì)象提供的接口。在本文的例子中,我們不對(duì)外部對(duì)象開放任何事件。

下面是COM對(duì)象完整的源代碼:
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 myC+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();
}

}
}

  在創(chuàng)建COM對(duì)象前,我們必須向COM Interop注冊(cè)該對(duì)象。右擊方案管理器中的工程名字,點(diǎn)擊快捷菜單上的“屬性”選項(xiàng),然后再點(diǎn)擊“配置”->“創(chuàng)建”,擴(kuò)展output小節(jié),將Register for COM Interop選項(xiàng)的值設(shè)置為true。這樣,一個(gè)COM對(duì)象就能夠與可管理性應(yīng)用程序進(jìn)行交互。
 
  為了使COM對(duì)象能夠被外部對(duì)象調(diào)用,類庫(kù)組合必須有一個(gè)強(qiáng)名字。創(chuàng)建強(qiáng)名字需要用到SN.EXE名字:
  sn -k Database_COM_Key.snk

  打開AssemblyInfo.cs,并修改下面一行的內(nèi)容:
  [assembly: AssemblyKeyFile("Database_COM_Key.snk")]

  創(chuàng)建對(duì)象。創(chuàng)建對(duì)象會(huì)生成一個(gè)可以被導(dǎo)入到可管理性或非可管理性代碼中的類庫(kù)。

第二部分:使用Visual C++創(chuàng)建訪問COM對(duì)象的客戶端軟件

·使用VC++開發(fā)環(huán)境創(chuàng)建一個(gè)簡(jiǎn)單的工程。

·使用#import directive導(dǎo)入類型庫(kù)。

·在界面中創(chuàng)建一個(gè)Smart Pointer,從接口中執(zhí)行COM類提供的功能。確保在應(yīng)用程序加載時(shí)添加CoInitialize()調(diào)用:

CoInitialize(NULL);
Database_COMObject:BCOM_InterfacePtr p(__uuidof(Database_COMObject:BCOM_Class));
db_com_ptr = p ;
db_com_ptr->Init("scott" , "tiger");

  下面的代碼對(duì)Customers數(shù)據(jù)庫(kù)表執(zhí)行一個(gè)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 ;


來(lái)源于北京教育招生網(wǎng)




歡迎光臨 電子科大論壇-非清水河畔 (http://www.hallmarkedu.com/) Powered by Discuz! X3.4