熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

用C#創建COM對象

2022-06-13   來源: .NET編程 
  在本篇文章中我們將討論下面的問題

·使用C#創建一個簡單的COM對象(使用COM的Interop特性)

·從VC++客戶端軟件中訪問COM客戶端軟件使用了TypeLibrary(TLB文件)為了簡單和方便開發人員使用測試起見我們使用了SQLSERVER數據庫軟件的缺省安裝中的Northwind數據庫

·修改COM對象中SQLServer的名字與SQLServer連接

·我們已經創建了連接數據庫用的分別為scotttiger的用戶名和口令我們可以使用它或者其他現有的用戶名和口令

第一部分用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需要運行guidgenexe工具軟件並選擇注冊表格式

下面是一個類界面

[Guid(CBFFDBC)]
public interface DBCOM_Interface
{
[DispId()]
void Init(string userid string password);
[DispId()]
bool ExecuteSelectCommand(string selCommand);
[DispId()]
bool NextRow();
[DispId()]
void ExecuteNonSelectCommand(string insCommand);
[DispId()]
string GetColumnData(int pos);
}

COM事件接口
// 事件接口Database_COMObjectEvents
[Guid(CECACDCF)
InterfaceType(ComInterfaceTypeInterfaceIsIDispatch)]
public interface DBCOM_Events
{
}


下面是實際的類定義

[Guid(EEFBDeeABEDBEDEE)
ClassInterface(ClassInterfaceTypeNone)
ComSourceInterfaces(typeof(DBCOM_Events))]
public class DBCOM_Class : DBCOM_Interface
{


需要注意的是在類的前面需要設置下面的特性

ClassInterface(ClassInterfaceTypeNone)
ComSourceInterfaces(typeof(DBCOM_Events))]

  ClassInterfaceTypeNone表示沒有為該類生成類接口如果沒有明確地實現接口類只能通過IDispatch提供後期綁定訪問用戶希望通過明確地由類實現的接口使外部對象能夠訪問類的功能這也是推薦的ClassInterfaceAttribute的設置

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

下面是COM對象完整的源代碼

using System;
using SystemRuntimeInteropServices;
using SystemIO;
using SystemText;
using SystemDataSqlClient;
using SystemWindowsForms ;

namespace Database_COMObject
{
[Guid(CBFFDBC)]
public interface DBCOM_Interface
{
[DispId()]
void Init(string userid string password);
[DispId()]
bool ExecuteSelectCommand(string selCommand);
[DispId()]
bool NextRow();
[DispId()]
void ExecuteNonSelectCommand(string insCommand);
[DispId()]
string GetColumnData(int pos);
}

// 事件接口Database_COMObjectEvents
[Guid(CECACDCF)
InterfaceType(ComInterfaceTypeInterfaceIsIDispatch)]
public interface DBCOM_Events
{
}


[Guid(EEFBDeeABEDBEDEE)
ClassInterface(ClassInterfaceTypeNone)
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=;
myConnection = new SqlConnection(myConnectString);
myConnectionOpen();
MessageBoxShow(CONNECTED);
}
catch(Exception e)
{
MessageBoxShow(eMessage);
}
}

public bool ExecuteSelectCommand(string selCommand)
{
if ( myReader != null )
myReaderClose() ;

SqlCommand myCommand = new SqlCommand(selCommand);
myCommandConnection = myConnection;
myCommandExecuteNonQuery();
myReader = myCommandExecuteReader();
return true ;
}

public bool NextRow()
{
if ( ! myReaderRead() )
{
myReaderClose();
return false ;
}
return true ;
}

public string GetColumnData(int pos)
{
Object obj = myReaderGetValue(pos);
if ( obj == null ) return ;
return objToString() ;
}

public void ExecuteNonSelectCommand(string insCommand)
{
SqlCommand myCommand = new SqlCommand(insCommand myConnection);
int retRows = myCommandExecuteNonQuery();
}

}
}

  在創建COM對象前我們必須向COM Interop注冊該對象右擊方案管理器中的工程名字點擊快捷菜單上的屬性選項然後再點擊配置>創建擴展output小節將Register for COM Interop選項的值設置為true這樣一個COM對象就能夠與可管理性應用程序進行交互
 
  為了使COM對象能夠被外部對象調用類庫組合必須有一個強名字創建強名字需要用到SNEXE名字
  sn k Database_COM_Keysnk

  打開AssemblyInfocs並修改下面一行的內容
  [assembly: AssemblyKeyFile(Database_COM_Keysnk)]

  創建對象創建對象會生成一個可以被導入到可管理性或非可管理性代碼中的類庫

第二部分使用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[];
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();
p = mData ;
m_address = (CString)p ;


From:http://tw.wingwit.com/Article/program/net/201311/15785.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.