千家信息网

.NET 4.0的ICustomQueryInterface新特性是什么

发表于:2024-10-18 作者:千家信息网编辑
千家信息网最后更新 2024年10月18日,本篇文章给大家分享的是有关.NET 4.0的ICustomQueryInterface新特性是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来
千家信息网最后更新 2024年10月18日.NET 4.0的ICustomQueryInterface新特性是什么

本篇文章给大家分享的是有关.NET 4.0的ICustomQueryInterface新特性是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

在.NET Framework v4.0发布的新功能中,在名字空间System.Runtime.InteropServices新增加了一个叫做ICustomQueryInterface的Interface, 顾名思义,这个Interface的功能就是使得用户可以自己控制QueryInterface这个COM最常用的函数的行为。在v4.0以前,所有作用于托管组件上的QI行为,都是由CLR内部的IUnkown:QueryInterface控制的,比如,如果你QI著名的IDispatch接口时,你得到的永远都是CLR提供的那个IDispatch,诸如此类的还有IMarshal/IProvideClassInfo等一些常用的Interface。如果你非常希望用自己的IDispatch实现来替换clr提供的实现,那么恭喜你,ICustomQueryInterface就是为你而生的!当然,ICustomQueryInterface所带来的,不仅仅是简单的Interface替换,它甚至可以使得Aggregate托管组件也成为现实。

让我们来看看这个ICustomQueryInterface的定义吧:

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

是的,就是这么简单,就一个GetInterface方法,再仔细看看它的方法参数,是不是和c++里面的QueryInterface有点神似啊。哈哈,其实你可以把它理解成QueryInterface的托管实现也无妨啊!不过它还有个小小的功能,就是如果自己不想处理这个QI,就返回NotHandled, clr看到这个返回值,就会调用自己的QI实现来帮你处理这个请求,爽吧。

让我们来看看有了这个Interface之后clr内部关于QI的处理流程图吧:


.NET 4.0新特性:ICustomQueryInterface

从这个图上我们可以看到,除了不能处理对IUnknown的QI请求(要求别太高嘛),其他统统OK!

理论一大堆了,来实战一下。

看看我们的托管组件的实现

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:

这里稍微做个解释,GetInterface的返回值如果是CustomQueryInterfaceResult.Failed,意思是QI失败。CustomQueryInterfaceResult.NotHandled意思是让clr去处理这个请求,CustomQueryInterfaceResult.Handled是告诉clr,已经处理好了,指针值保存在intf里面,直接返回给用户就可以了。

再来看看我们的客户端

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);

再来看看我们的输出结果。

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新特性是什么,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

0