本主題說明在 JavaScript 延伸模組中使用原生偵錯工具物件的其他詳細資料。
原生調試程序物件代表調試程式環境的各種建構和行為。 物件可以傳遞至 (或取得) JavaScript 延伸模組,以操作偵錯工具的狀態。
如需偵錯工具物件 JavaScript 延伸模組的相關資訊,請參閱 JavaScript 延伸模組中的原生偵錯工具物件。
如需使用 JavaScript 的一般資訊,請參閱 JavaScript 偵錯工具腳本。
例如,對於 JavaScript 腳本和延伸模組,偵錯工具小組在 https://github.com/Microsoft/WinDbg-Samples 上託管了一個 GitHub 儲存庫。
JavaScript 延伸模組中的偵錯工具物件
傳遞原生物件
偵錯工具物件可以透過多種方式傳遞至 JavaScript 延伸模組或取得。
- 它們可以傳遞給JavaScript函數或方法
- 它們可以是 JavaScript 原型的實例物件 (例如,作為視覺化工具)
- 它們可以透過設計用來創建原生除錯工具物件的主機方法被傳回
- 它們可以從設計用來建立偵錯工具原生物件的主機端方法中傳回
傳遞至 JavaScript 延伸模組的偵錯工具物件具有本節所述的一組功能。
- 屬性存取
- 預測名稱
- 與原生偵錯工具物件相關的特殊類型
- 其他屬性
屬性訪問
雖然 JavaScript 提供者本身會放置物件上的一些內容,但進入 JavaScript 的原生物件上的大部分內容都是由資料模型提供。 這表示對於 object.propertyName 或 object[propertyName] ---屬性存取,將會發生下列情況。
- 如果 propertyName 是 JavaScript 提供者本身投影到物件上的屬性名稱,它會先解析為 this;否則
- 如果 propertyName 是資料模型 (另一個視覺化工具) 投影到物件上的索引鍵名稱,則它會解析為第二個名稱;否則
- 如果 propertyName 是原生物件的欄位名稱,則會解析為此名稱;否則
- 如果物件是指標,則指標將被解參考,並且上面的循環將繼續(解參考物件的投影的屬性,後面跟著一個鍵,接著是原生欄位)
JavaScript 中屬性存取的一般方式 -- object.propertyName 和 object[propertyName] -- 會存取物件的基礎原生欄位,就像偵錯工具中的 'dx' 命令一樣。
預計名稱
下列屬性 (和方法) 會投影到進入 JavaScript 的原生物件上。
| 方法 | 簽名 | 說明 |
|---|---|---|
| 主機環境 | 房產 | 傳回一個物件,代表物件所在的內容(位址空間、偵錯目標等... |
| targetLocation | 房產 | 傳回一個物件,該物件是物件在位址空間內的位置的抽象化(虛擬位址、暫存器、子暫存器等... |
| targetSize | 房產 | 傳回物件的大小(實際上相當於:sizeof(<TYPE OF OBJECT>)) |
| 新增父模型 | .addParentModel(物件) | 將新的父模型 (類似於 JavaScript 原型,但在資料模型端) 新增至物件 |
| 移除父模型 | .removeParentModel(物件) | 從物件中移除指定的父項模型 |
| 執行期類型化物件 | 房產 | 對物件執行分析,並嘗試轉換為執行階段(最具衍生性)類型。 |
| 目標類型 | 房產 | JavaScript 擴充功能可以直接存取底層語言的類型系統。 此存取權是透過類型物件的概念來表示。 如需詳細資訊,請參閱 JavaScript 延伸模組中的原生偵錯工具物件 - 類型物件 |
如果物件是指標,則下列屬性 (和方法) 會投影到進入 JavaScript 的指標上:
| 屬性名稱 | 簽名 | 說明 |
|---|---|---|
| 新增 | .add(值) | 在指標與指定值之間執行指標數學加法 |
| 地址 | 房產 | 將指標的位址傳回為 64 位序數物件 (函式庫類型) |
| 取值 (Dereference) | .dereference() | 取消參考指標並傳回基礎物件 |
| 是空 | 房產 | 傳回指標值是否為 nullptr (0) |
與原生偵錯工具物件相關的特殊類型
位置物件
從原生物件的 targetLocation 屬性傳回的位置物件包含下列屬性 (和方法) 。
| 屬性名稱 | 簽名 | 說明 |
|---|---|---|
| 新增 | .add(值) | 將絕對位元組位移新增至位址。 |
| 差集 | .subtract(值) | 從位置減去絕對位元組的偏移量。 |
其他屬性
可疊代性
任何被數據模型理解為可迭代的對象(無論是原生陣列還是具有使其可迭代的可視化工具(如 NatVis 或其他工具)),都會在其上附加一個迭代器函數,這個函數是通過 ES6 標準的 Symbol.iterator 進行索引的。 這意味著您可以在 JavaScript 中迭代原生對象,如下所示。
function iterateNative(nativeObject)
{
for (var val of nativeObject)
{
//
// val will contain each element iterated from the native object. This would be each element of an array,
// each element of an STL structure which is made iterable through NatVis, each element of a data structure
// which has a JavaScript iterator accessible via [Symbol.iterator], or each element of something
// which is made iterable via support of IIterableConcept in C/C++.
//
}
}
索引性
透過序數在一維中理解為可索引的物件(例如:原生陣列)將透過標準屬性存取運算子 -- object[index] 在 JavaScript 中可建立索引。 如果物件可依名稱編製索引,或可在多個維度中編製索引,則 getValueAt 和 setValueAt 方法會投影到物件上,以便 JavaScript 程式碼可以使用索引子。
function indexNative(nativeArray)
{
var first = nativeArray[0];
}
字串轉換
任何透過支援 IStringDisplayableConcept 或 NatVis DisplayString 元素進行顯示字串轉換的原生物件,都會透過標準 JavaScript toString 方法存取該字串轉換。
function stringifyNative(nativeObject)
{
var myString = nativeObject.toString();
}
建立原生偵錯工具物件
如前所述,JavaScript 腳本可以透過多種方式之一將本機物件傳遞至 JavaScript,也可以透過呼叫主機函式庫來建立它們。 使用下列函式來建立原生偵錯工具物件。
| 方法 | 簽名 | 說明 |
|---|---|---|
host.getModuleSymbol |
getModuleSymbol(模組名稱,符號名稱,[contextInheritor]) getModuleSymbol(模組名稱、符號名稱、[類型名稱]、[contextInheritor]) |
傳回在特定模組內對應於全域符號的物件。 模組名稱和符號名稱是字串。 如果提供選用的 contextInheritor 引數,則會在與傳遞物件相同的內容 (位址空間、偵錯目標) 內查閱模組和符號。 如果未提供引數,則會在偵錯工具的當前環境中查找模組和符號。 不是一次性測試腳本的 JavaScript 擴充功能應該一律提供明確的環境定義。 如果提供選擇性的 typeName 引數,則會假設符號是傳遞的類型,且會忽略符號 () 中指出的類型。 請注意,任何預期在模組公用符號上運作的呼叫端都應該一律提供明確的類型名稱。 |
host.getModuleContainingSymbol (取得包含符號的模組) |
getModuleContainingSymbol(位置, [contextInheritor]) | 傳回包含給定位址的符號(例如:函數或資料)。 請注意,這僅在包含給定地址的模塊有 私有 符號時才有效。 如果提供選用的 contextInheritor 引數,則會在與傳遞物件相同的內容 (位址空間、偵錯目標) 內查閱模組和符號。 如果未提供引數,則會在偵錯工具目前的內容中查找模組和符號。 不是一次性測試腳本的 JavaScript 擴充功能應該一律提供明確的環境定義。 |
host.createPointer物件 |
createPointerObject(位址、模組名稱、類型名稱、[contextInheritor]) |
在指定的位址或位置建立指標物件。 模組名稱和類型名稱是字串。 如果提供選用的 contextInheritor 引數,則會在與傳遞物件相同的內容 (位址空間、偵錯目標) 內查閱模組和符號。 如果未提供引數,則會在除錯器目前的上下文中查閱模組和符號。 不是一次性測試腳本的 JavaScript 擴充功能應該一律提供明確的環境定義。 |
host.createTypedObject |
createTypedObject(位置, 模組名稱, 類型名稱, [contextInheritor]) |
建立物件,代表指定位置偵錯目標位址空間內的原生類型物件。 模組名稱和類型名稱是字串。 如果提供選用的 contextInheritor 引數,則會在與傳遞物件相同的內容 (位址空間、偵錯目標) 內查閱模組和符號。 如果未提供引數,則會在偵錯工具目前的內容中查找模組和符號。 不是一次性測試腳本的 JavaScript 擴充功能應該一律提供明確的環境定義。 |
JavaScript 延伸模組的主機 API
JavaScript 提供者會將名為 host 的物件插入其載入之每個腳本的全域命名空間中。 此物件可讓您存取腳本的重要功能,以及偵錯工具命名空間的存取權。 它分兩個階段進行設置。
階段 1:在任何腳本執行之前,主機物件僅包含腳本初始化自身並註冊其擴充點 (作為生產者和取用者) 所需的最小功能集。 根和初始化程式碼並非要操作偵錯目標的狀態或執行複雜的作業,因此,在 initializeScript 方法傳回之前,主機不會完全填入。
階段 2:在 initializeScript 傳回之後,主機物件會填入操作偵錯目標狀態所需的一切。
主機物件層級
一些關鍵功能直接位於主機物件下方。 其餘部分是子命名空間。 命名空間包括下列項目。
| Namespace | 說明 |
|---|---|
| 診斷 | 協助診斷和調試腳本代碼的功能 |
| 記憶體 | 在偵錯目標內啟用記憶體讀取和寫入的功能 |
根層級
直接在主機物件內,可以找到下列屬性、方法和建構函式。
| 名稱 | 簽名 | 當前階段 | 說明 |
|---|---|---|---|
| CreatePointer物件 | createPointerObject(位址、模組名稱、類型名稱、[contextInheritor]) |
2 | 在指定的位址或位置建立指標物件。 模組名稱和類型名稱是字串。 選用的 contextInheritor 引數與 getModuleSymbol 一樣運作。 |
| createTypedObject | createTypedObject(位置, 模組名稱, 類型名稱, [contextInheritor]) |
2 | 建立物件,代表指定位置偵錯目標位址空間內的原生類型物件。 模組名稱和類型名稱是字串。 選用的 contextInheritor 引數與 getModuleSymbol 一樣運作。 |
| currentProcess | 房產 |
2 | 傳回代表偵錯工具目前進程的物件 |
| 當前會話 | 房產 |
2 | 傳回代表偵錯工具目前會話的物件 (目標、傾印等) 正在偵錯 |
| 目前執行緒 | 房產 |
2 | 傳回代表偵錯工具目前執行緒的物件 |
| 評估運算式 | evaluateExpression(expression, [contextInheritor]) |
2 | 這會呼叫調試主機,以僅使用調試目標語言來評估表達式。 如果提供了可選的 contextInheritor 引數,則會在引數的上下文(例如:位址空間和偵錯目標)中評估運算式;否則,將會在偵錯工具的目前內容中評估 |
| evaluateExpressionInContext | evaluateExpressionInContext(context, expression) |
2 | 這會調用偵錯主機,僅使用偵錯目標的語言來評估運算式。 上下文引數表示隱含的 this 指標用於評估。 運算式將在 上下文 引數指示的上下文(例如:地址空間和調試目標)中進行評估。 |
| getModuleSymbol | getModuleSymbol(模組名稱,符號名稱,[contextInheritor]) |
2 | 傳回特定模組內全域符號的物件。 模組名稱和符號名稱是字串。 如果提供選用的 contextInheritor 引數,則會在與傳遞物件相同的內容 (位址空間、偵錯目標) 內查閱模組和符號。 如果未提供引數,則會在除錯程式的目前內容中查閱模組與符號。 不是一次性腳本的 JavaScript 擴充功能應一律提供明確的內容 |
| getNamedModel | getNamedModel(模型名稱) |
2 | 傳回針對指定名稱註冊的資料模型。 請注意,針對尚未註冊的名稱稱呼這是完全合法的。 這樣做會為該名稱建立存根,並在註冊時對實際物件進行存根的操作 |
| 索引值 | new indexedValue(值,索引) |
2 | 物件的建構函式,可從 JavaScript 迭代器傳返回來,以便將預設的索引集指派給迭代值。 索引集必須表示為 JavaScript 陣列。 |
| Int64 | new Int64(值, [高值]) |
1 | 這會建構一個 Int64 型別的程式庫。 單一引數版本會採用任何可以封裝成 Int64 的值 (,無需轉換) ,並將其放入這樣的值中。 如果提供選用的第二個引數,則第一個引數的轉換會封裝到較低的 32 位元中,而第二個引數的轉換會封裝到較高的 32 位元中。 |
| namedModelParent | new namedModelParent(物件, 名稱) |
1 | 一個物件的建構函數,旨在放置於從 initializeScript 傳回的陣列中,這表示使用 JavaScript 原型或 ES6 類別作為資料模型的父級延伸,並賦予該資料模型一個特定名稱。 |
| namedModel註冊 | new namedModelRegistration(物件, 名稱) |
1 | 一個物件的建構函式,用於放置在從 initializeScript 傳回的陣列中,這代表透過已知名稱將 JavaScript 原型或 ES6 類別註冊為資料模型,以便其他擴充功能可以找到並擴展 |
| 命名空間 | 房產 |
2 | 提供偵錯工具根命名空間的直接存取權。 例如,可以透過 host.namespace.Debugger.Sessions.First() 存取第一個偵錯目標的進程清單。使用此屬性的處理程序 |
| registerNamedModel | registerNamedModel(物件,模型名稱) |
2 | 這會將 JavaScript 原型或 ES6 類別註冊為指定名稱下的資料模型。 這類註冊可讓其他腳本或偵錯擴充程式找到並擴展原型或類別。 請注意,腳本應該偏好從其 initializeScript 方法傳回 namedModelRegistration 物件,而不是命令式執行此動作。 任何進行命令式變更的腳本都必須具有 initializeScript 方法才能清除。 |
| 註冊類型簽名擴充功能 | registerExtensionForTypeSignature(物件, 類型簽名) |
2 | 這會將 JavaScript 原型或 ES6 類別註冊成為原生類型的擴充資料模型,根據所提供的類型簽章。 請注意,腳本應該偏好從其 initializeScript 方法傳回 typeSignatureExtension 物件,而不是命令式執行此動作。 任何進行命令式變更的腳本都必須具有 initializeScript 方法才能清除。 |
| registerPrototypeForTypeSignature | registerPrototypeForTypeSignature(物件,typeSignature) |
2 | 這會將 JavaScript 原型或 ES6 類別根據提供的類型簽章,註冊為原生類型的標準數據模型(例如:可視化工具)。 請注意,腳本應該偏好從其 initializeScript 方法傳回 typeSignatureRegistration 物件,而不是命令式執行此動作。 任何進行命令式變更的腳本都需要具有 uninitializeScript方法才能清除。 |
| 解析Int64 | parseInt64(字串, [基數]) |
1 | 這個方法的運作方式與標準 JavaScript parseInt 方法類似,不同之處在於它會傳回程式庫 Int64 類型。 如果提供基數,則解析將在 2、8、10 或 16 進制中進行,如前所述。 |
| typeSignatureExtension | new typeSignatureExtension(物件, typeSignature, [模組名稱], [minVersion], [maxVersion]) |
1 | 一個物件的建構函式,旨在放置在從 initializeScript 傳回的陣列中,這代表透過 JavaScript 原型或 ES6 類別的類型簽章描述的原生類型的擴展。 這類註冊會將欄位新增至符合簽章的任何類型的偵錯工具視覺化,並不是完全接管它。 選擇性模組名稱和版本可以限制註冊。 版本指定為「1.2.3.4」樣式字串。 |
| 類型簽名登錄 | new typeSignatureRegistration(物件, typeSignature, [模組名稱], [minVersion], [maxVersion]) |
1 | 一個物件的建構函式,旨在放置在從 initializeScript 傳回的陣列中,這代表 JavaScript 原型或 ES6 類別對原生類型簽章的規範註冊。 這種註冊會「接管」偵錯工具對任何符合該簽章類型的視覺化展示,而不僅僅是擴充它。 選擇性模組名稱和版本可以限制註冊。 版本指定為「1.2.3.4」樣式字串。 |
| 注銷命名模型 | unregisterNamedModel(模型名稱) |
2 | 這會取消註冊資料模型,使其無法依指定名稱進行查閱,並復原 registerNamedModel 所執行的任何作業 |
| 取消註冊擴充模組類型簽名 | unregisterExtensionForTypeSignature(物件, 類型簽名, [模組名稱], [minVersion], [maxVersion]) |
2 | 這會取消註冊 JavaScript 原型或 ES6 類別,使其不再是原生類型的擴充資料模型,如所提供的類型簽章所提供。 這是邏輯上撤銷「registerExtensionForTypeSignature」的操作。 請注意,腳本應該偏好從其 initializeScript 方法傳回 typeSignatureExtension 物件,而不是命令式執行此動作。 任何進行命令式變更的腳本都必須具有 initializeScript 方法才能清除。 選擇性模組名稱和版本可以限制註冊。 版本指定為「1.2.3.4」樣式字串。 |
| 取消註冊PrototypeForTypeSignature | unregisterPrototypeForTypeSignature(物件, 類型簽章, [模組名稱], [minVersion], [maxVersion]) |
2 | 這會取消註冊 JavaScript 原型或 ES6 類,使其不再成為提供的類型簽名所給定的原生類型的規範數據模型(例如:可視化工具)。 這是函式 registerPrototypeForTypeSignature 的邏輯上的撤銷。 請注意,腳本應該偏好從其 initializeScript 方法傳回 typeSignatureRegistration 物件,而不是命令式執行此動作。 任何進行命令式變更的腳本都需要具有 uninitializeScript 方法才能清除。 選擇性模組名稱和版本可以限制註冊。 版本指定為「1.2.3.4」樣式字串。 |
診斷功能
主機物件的診斷子命名空間包含下列項目。
| 名稱 | 簽名 | 當前階段 | 說明 |
|---|---|---|---|
| 除錯日誌 | debugLog(物件...) | 1 | 這提供給腳本擴展模組的 printf 樣式除錯功能。 目前,debugLog 的輸出會路由傳送至偵錯器的輸出主控台。 稍後的某個時間點,我們計劃提供對此輸出進行路由選擇的靈活性。 注意:這不應用作將使用者輸出列印到主控台的方法。 將來可能不會路由到那裡。 |
記憶體功能
主機物件的記憶體子命名空間包含下列項目。
| 名稱 | 簽名 | 當前階段 | 說明 |
|---|---|---|---|
| 讀取記憶體值 | readMemoryValues(位置、numElements、[元素大小]、[isSigned]、[contextInheritor]) |
2 | 這會從偵錯目標的位址空間讀取原始值陣列,並將類型化陣列放在此記憶體的視圖之上。 提供的位置可以是位址 (64 位值)、位置物件或原生指標。 陣列的大小由 numElements 引數表示。 陣列中每個元素的大小(和類型)由可選的 elementSize 和 isSigned 引數提供。 如果未提供這類引數,則預設值為位元組 (無正負號 / 1 位元組) 。 如果提供了可選的 contextInheritor 參數,則將在參數指示的上下文(例如:位址空間和偵錯目標)中讀取記憶體;否則,將會從偵錯工具目前的內容讀取它。 請注意,在 8、16 和 32 位值上使用此方法會導致將快速類型化視圖放置在讀取記憶體上。 在 64 位值上使用此方法會導致構建 64 位庫類型的陣列,這要昂貴得多! |
| 讀取字串 | readString(位置,[contextInheritor]) readString(位置, [長度], [contextInheritor]) |
2 | 這會從偵錯目標的位址空間讀取狹窄的 (目前字碼頁) 字串,將它轉換為 UTF-16,並將結果傳回為 JavaScript 字串。 如果無法讀取記憶體,它可能會拋出異常。 提供的位置可以是位址 (64 位值)、位置物件或原生字元。 如果提供了可選的 contextInheritor 參數,則將在參數指示的上下文(例如:位址空間和偵錯目標)中讀取記憶體;否則,將會從偵錯工具目前的內容讀取它。 如果提供選用 長度 引數,則讀取字串將具有指定的長度。 |
| 讀取寬字串 | readWideString(位置, [contextInheritor]) readWideString(位置, [長度], [contextInheritor]) |
2 | 這會從偵錯目標的位址空間讀取寬 (UTF-16) 字串,並將結果傳回為 JavaScript 字串。 如果無法讀取記憶體,它可能會拋出異常。 提供的位置可以是位址 (64 位值)、位置物件或原生wchar_t。 如果提供了可選的 contextInheritor 參數,則將在參數指示的上下文(例如:位址空間和偵錯目標)中讀取記憶體;否則,將會從偵錯工具目前的內容讀取它。 如果提供選用 長度 引數,則讀取字串將具有指定的長度。 |
JavaScript 中的資料模型概念
資料模型對應
下列資料模型概念對應至 JavaScript。
| 概念 | 原生介面 | JavaScript 等價 |
|---|---|---|
| 字串轉換 | IStringDisplayableConcept(字串顯示概念) | 標準:toString(...){...} |
| 可疊代性 | IIterableConcept | 標準: [Symbol.iterator](){...} |
| 可索引性 | 可索引概念 | 通訊協定:getDimensionality(...) / getValueAt(...) / setValueAt(...) |
| 執行階段類型轉換 | IPreferredRuntimeTypeConcept | 協定:getPreferredRuntimeTypedObject(...) |
字串轉換
字串轉換概念 (IStringDisplayableConcept) 會直接轉譯為標準 JavaScript toString 方法。 由於所有 JavaScript 物件都有字串轉換 (如果未在其他地方提供,則由 Object.prototype 提供),因此傳回給資料模型的每個 JavaScript 物件都可以轉換為顯示字串。 覆寫字串轉換只需實作自己的 toString。
class myObject
{
//
// This method will be called whenever any native code calls IStringDisplayableConcept::ToDisplayString(...)
//
toString()
{
return "This is my own string conversion!";
}
}
可疊代性
資料模型的物件是否可疊代的概念直接對應至物件是否可疊代的 ES6 通訊協定。 任何具有 [Symbol.iterator] 方法的物件都被視為可迭代。 這樣的實現將使對象可迭代。
只能疊代的物件可以具有如下實作。
class myObject
{
//
// This method will be called whenever any native code calls IIterableConcept::GetIterator
//
*[Symbol.iterator]()
{
yield "First Value";
yield "Second Value";
yield "Third Value";
}
}
必須特別考慮可迭代和可索引的物件,因為從迭代器傳回的物件必須包含索引以及透過特殊傳回類型的值。
可迭代和可索引
可迭代且可索引的物件需要迭代器的特殊傳回值。 迭代器不會產生值,而是產生 indexedValue 的實例。 索引會以第二個引數中的陣列形式傳遞至 indexedValue 建構函式。 它們可以是多維度的,但必須符合索引子通訊協定中傳回的維度。
此程式碼顯示實作範例。
class myObject
{
//
// This method will be called whenever any native code calls IIterableConcept::GetIterator
//
*[Symbol.iterator]()
{
//
// Consider this a map which mapped 42->"First Value", 99->"Second Value", and 107->"Third Value"
//
yield new host.indexedValue("First Value", [42]);
yield new host.indexedValue("Second Value", [99]);
yield new host.indexedValue("Third Value", [107]);
}
}
索引性
與 JavaScript 不同,資料模型會非常清楚地區分資料模型中的屬性存取和索引。 任何想要在資料模型中呈現為可索引的 JavaScript 物件都必須實作通訊協定,其中包含傳回索引子維度的 getDimensionality 方法,以及一對選擇性的 getValueAt 和 setValueAt 方法,這些方法會在提供的索引處執行物件的讀取和寫入。 如果物件是唯讀或唯寫,則可以省略 getValueAt 或 setValueAt 方法
class myObject
{
//
// This method will be called whenever any native code calls IIndexableConcept::GetDimensionality or IIterableConcept::GetDefaultIndexDimensionality
//
getDimensionality()
{
//
// Pretend we are a two dimensional array.
//
return 2;
}
//
// This method will be called whenever any native code calls IIndexableConcept::GetAt
//
getValueAt(row, column)
{
return this.__values[row * this.__columnCount + column];
}
//
// This method will be called whenever any native code calls IIndexableConcept::SetAt
//
setValueAt(value, row, column)
{
this.__values[row * this.__columnCount + column] = value;
}
}
執行階段類型轉換
這僅與針對類型系統(原生)類型註冊的JavaScript原型/類別相關。 偵錯工具通常能夠執行分析 (例如 Run-Time 類型資訊 (RTTI) /v 表分析) ,以從程式碼中表示的靜態類型判斷物件的真實執行階段類型。 針對原生類型註冊的資料模型可以透過 IPreferredRuntimeTypeConcept 的實作覆寫此行為。 同樣地,針對原生物件註冊的 JavaScript 類別或原型可以透過實作包含 getPreferredRuntimeTypedObject 方法的通訊協定來提供自己的實作。
請注意,雖然這個方法在技術上可以傳回任何東西,但若它傳回的內容並非真正的運行時類型或其衍生類型,則被視為不良的做法。 這可能會對偵錯工具的使用者造成重大混淆。 然而,覆寫這個方法對於類似 C 語言風格的標頭和物件風格的實作等情況可能是有價值的......
class myNativeModel
{
//
// This method will be called whenever the data model calls IPreferredRuntimeTypeConcept::CastToPreferredRuntimeType
//
getPreferredRuntimeTypedObject()
{
var loc = this.targetLocation;
//
// Perform analysis...
//
var runtimeLoc = loc.Add(runtimeObjectOffset);
return host.createTypedObject(runtimeLoc, runtimeModule, runtimeTypeName);
}
}