在ASP開發中,我們經常會用到類似這樣的調用 oUserName=Request("UserName")。可以肯定的是,我們需要得到的是一個字符串值,事實上,我們也把oUserName作爲一個字符值來使用。
作爲一個完整的調用應該是這樣的:oUserName=CStr(Request.Item("UserName"))
接下來我們看,Request對象是如何通過COM自動化技術來支持形如Request("UserName")的調用的。
通過查看類型庫,知道Request對象派生自接口IRequest,IRequest提供如下只讀屬性的申明。
[id(00000000), propget]
HRESULT Item(
[in] BSTR bstrVar,
[out, retval] IDispatch** ppObjReturn);
只讀屬性Item的DISPID爲0,說明它是一個缺省屬性,通過腳本調用時,不必顯式寫出。該屬性的傳入參數是一個字符串,傳出值是一個IDispatch*接口指針。原來,上面得到的oUserName其實是一個IDispatch接口,並不是字符串值,只是在後面的調用中會自動實現IDispatch接口到字符串的轉換,從而在表面上我們可以直接把它作爲一個字符串來看待。
下面的問題是,IDispatch接口怎麼就會自動轉換。在自動化編程中,對於各種自動化類型之間的轉換主要通過VariantChangeType和VariantChangeTypeEx進行。
下面是函數VariantChangeTypeEx的聲明
HRESULT VariantChangeTypeEx(
VARIANTARG * pvargDest,
VARIANTARG * pvarSrc,
LCID lcid,
unsigned short wFlags,
VARTYPE vt
);
MSDN中對函數有這麼一段解釋。
An object is coerced to a value by invoking the object's Value property (DISPID_VALUE).
翻譯過來是,通過調用對象的Value屬性(屬性ID爲DISPID_VALUE),將此對象強制轉換爲一個值。
其中DISPID_VALUE就是0,VariantChangeType在進行轉換時,如果發現pvarSrc是一個IDispatch接口,就會自動調用DISPID爲0的屬性方法,從而由這個屬性方法來具體實現IDispatch接口到其他值的轉換。
IDispatch接口具體轉換成什麼類型的值,由DISPID爲0的屬性方法決定。
下面我們寫一個簡單的實例:
定義一個對象CTest,實現接口ITest,ITest又派生自IDispatch;ITest定義一個屬性Item
第一步:先生成接口ITest及對象CTest
interface ITest: IDispatch {
[id(00000000), propget]
HRESULT Item(
[out, retval] VARIANT* pVariantReturn);
};
class ATL_NO_VTABLE CTest :
public CComObjectRootEx,
public CComCoClass,
public IDispatchImpl
{
public:
........................
public:
// ITest Methods
public:
STDMETHOD(get_Item)(VARIANT * pVariantReturn)
{
CComVariant pvResult=L"This is a test";
pvResult.Detach(pVariantReturn);
return S_OK;
}
第二步:
在其他要實現的對象中
STDMETHOD(get_Item)(BSTR bstrVar, LPDISPATCH * ppObjReturn)
{
CComObject *pTest;
CComObject::CreateInstance(&pTest);
return pTest->QueryInterface(IID_IDispatch,(void**)ppObjReturn);
}