溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

.NET 4.0的ICustomQueryInterface新特性是什么

發(fā)布時(shí)間:2021-11-25 09:12:24 來(lái)源:億速云 閱讀:112 作者:柒染 欄目:編程語(yǔ)言

本篇文章給大家分享的是有關(guān).NET 4.0的ICustomQueryInterface新特性是什么,小編覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

在.NET Framework v4.0發(fā)布的新功能中,在名字空間System.Runtime.InteropServices新增加了一個(gè)叫做ICustomQueryInterface的Interface, 顧名思義,這個(gè)Interface的功能就是使得用戶可以自己控制QueryInterface這個(gè)COM最常用的函數(shù)的行為。在v4.0以前,所有作用于托管組件上的QI行為,都是由CLR內(nèi)部的IUnkown:QueryInterface控制的,比如,如果你QI著名的IDispatch接口時(shí),你得到的永遠(yuǎn)都是CLR提供的那個(gè)IDispatch,諸如此類(lèi)的還有IMarshal/IProvideClassInfo等一些常用的Interface。如果你非常希望用自己的IDispatch實(shí)現(xiàn)來(lái)替換clr提供的實(shí)現(xiàn),那么恭喜你,ICustomQueryInterface就是為你而生的!當(dāng)然,ICustomQueryInterface所帶來(lái)的,不僅僅是簡(jiǎn)單的Interface替換,它甚至可以使得Aggregate托管組件也成為現(xiàn)實(shí)。

讓我們來(lái)看看這個(gè)ICustomQueryInterface的定義吧:

  1: public interface ICustomQueryInterface  2: {  3:     CustomQueryInterfaceResult GetInterface([In]ref Guid iid, out IntPtr ppv);  4: }  5:

是的,就是這么簡(jiǎn)單,就一個(gè)GetInterface方法,再仔細(xì)看看它的方法參數(shù),是不是和c++里面的QueryInterface有點(diǎn)神似啊。哈哈,其實(shí)你可以把它理解成QueryInterface的托管實(shí)現(xiàn)也無(wú)妨啊!不過(guò)它還有個(gè)小小的功能,就是如果自己不想處理這個(gè)QI,就返回NotHandled, clr看到這個(gè)返回值,就會(huì)調(diào)用自己的QI實(shí)現(xiàn)來(lái)幫你處理這個(gè)請(qǐng)求,爽吧。

讓我們來(lái)看看有了這個(gè)Interface之后clr內(nèi)部關(guān)于QI的處理流程圖吧:

.NET 4.0的ICustomQueryInterface新特性是什么
.NET 4.0新特性:ICustomQueryInterface

從這個(gè)圖上我們可以看到,除了不能處理對(duì)IUnknown的QI請(qǐng)求(要求別太高嘛),其他統(tǒng)統(tǒng)OK!

理論一大堆了,來(lái)實(shí)戰(zhàn)一下。

看看我們的托管組件的實(shí)現(xiàn)

1: using System;
2: using System.Runtime.InteropServices;
3:
4: namespace States
5: {   
6:     [Guid("00020400-0000-0000-C000-000000001147")]
7:     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
8:     public interface ICQ
9:     {
10:         int func();
11:         void slot2();
12:         void slot3();
13:         void slot4();
14:     }
15:
16:     [Guid("11120400-0000-0000-C000-000000001148")]
17:     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
18:     public interface IA
19:     {
20:         int FuncA();
21:     }
22:
23:     [Guid("22220400-0000-0000-C000-000000001149")]
24:     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
25:     public interface IB
26:     {
27:         int FuncB();
28:     }
29:
30:
31:
32:     [Guid("00020400-0000-0000-C000-000000001150")]
33:     [ClassInterface(ClassInterfaceType.None)]
34:     public class StatesComServer : ICustomQueryInterface, ICQ, IA, IB
35:     {
36:           public readonly Guid IID_IA = new Guid("11120400-0000-0000-C000-000000001148");
37:        
38:           public CustomQueryInterfaceResult GetInterface([In]ref Guid iid, out IntPtr intf)
39:           {
40:                 if (iid == WellKnownGuids.IID_IDispatch)
41:                 {
42:                     intf = Marshal.GetComInterfaceForObject(this, typeof(ICQ), CustomQueryInterfaceMode.Ignore);
43:                     return CustomQueryInterfaceResult.Handled;
44:                 }
45:
46:                 if (iid == IID_IA)
47:                 {
48:                     intf = IntPtr.Zero;
49:                     return CustomQueryInterfaceResult.Failed;
50:                 }
51:
52:                 intf = IntPtr.Zero;
53:                 return CustomQueryInterfaceResult.NotHandled;
54:           }
55:
56:           public int func()
57:           {
58:               Console.WriteLine("This is Interface ICQ, not the IDispatch!!!");
59:                return 2008;
60:           }
61:
62:           public int FuncA()
63:           {
64:               Console.WriteLine("This is Interface IA!!!");
65:               return 3008;
66:           }
67:
68:           public int FuncB()
69:           {
70:               Console.WriteLine("This is Interface IB!!!");
71:               return 4008;
72:           }
73:
74:
75:         #region Empty Functions
76:           public void slot2() { }
77:           public void slot3() { }
78:           public void slot4() { }
79:         #endregion
80:     }
81:
82: }
83:

這里稍微做個(gè)解釋?zhuān)珿etInterface的返回值如果是CustomQueryInterfaceResult.Failed,意思是QI失敗。CustomQueryInterfaceResult.NotHandled意思是讓clr去處理這個(gè)請(qǐng)求,CustomQueryInterfaceResult.Handled是告訴clr,已經(jīng)處理好了,指針值保存在intf里面,直接返回給用戶就可以了。

再來(lái)看看我們的客戶端

IDispatch * pDisp = NULL;  printf("Scenario 1: QI IDispatch interface, Expected the Custom IDispatch interface\n");  hresult = pUnknown->QueryInterface(IID_IDispatch, (void**)&pDisp);   UINT count  = 0;  hresult = pDisp->GetTypeInfoCount(&count);  printf("Return value of GetTypeInfoCount is %d\n", count);     IA * pA = NULL;  printf("Scenario 2: QI IA interface, Expected failed\n");  hresult = pUnknown->QueryInterface(IID_IA, (void**)&hresult);  if (FAILED(hresult))  {    printf("Failed to QI IA with error code %x\n", count);    }  IB * pB = NULL;  printf("Scenario 3: QI IB interface interface, Expected the IB interface\n");  hresult = pUnknown->QueryInterface(IID_IB, (void**)&pB);  long i  = 0;  hresult = pB->FuncB(&i);

再來(lái)看看我們的輸出結(jié)果。

Scenario 1: QI IDispatch interface, Expected the Custom IDispatch interface This is Interface ICQ, not the IDispatch!!!  Return value of GetTypeInfoCount is 2008  Scenario 2: QI iA interface, Expected failed  Failed to QI IA with error code 7d8  Scenario 3: QI IB interface interface, Expected the IB interface This is Interface IB!!!

以上就是.NET 4.0的ICustomQueryInterface新特性是什么,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見(jiàn)到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI