.NET 4.0 Interop新特性ICustomQueryInterface (转载)

news/2024/9/20 5:22:40
.NET 4.0 Interop新特性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托管组件也成为现实,wow,如果你了解Aggregation的话,一定会因此而雀跃不已的。我会在另一篇文章中通过例程给大家做一个详细的介绍。

让我们来看看这个Interface的定义吧

  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的处理流程图吧(画的是英文版,烦请大家将就一下啦,没装viso,画图超级累啊!!!!)

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: 

这里有两个地方需要解释一下

1)对于ICQ这个接口,他实际上是作为自定义的IDispatch出现的,所以理论上应该他所有的函数声明应该和IDispatch保持一致,但是个人比较偷懒,毕竟这只是一个例程,主要是将如何使用ICustomQueryInterface这个接口,所以后三个方法的用途仅仅是为了保持ICQ的虚拟函数表(一共4个函数)和IDispatch保持一致,如果真的有人在客户端调IDispatch.Invoke(函数表中的第四个函数)的话,那调用必然会被重定向到ICQ.slot4,因为两个函数的参数声明完全不一样,AccessViolationException就无法避免了。

2)再讲一下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**)&pA);
  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!!!

Published Monday, August 10, 2009 11:34 AM by SilverlightShanghai

转自:http://blogs.msdn.com/silverlightshanghai/archive/2009/08/10/net-4-0-interop-icustomqueryinterface.aspx

 

转载于:https://www.cnblogs.com/wuhenke/archive/2010/01/23/1654657.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pgtn.cn/news/17818.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

相机标定(1)

理解相机标定就要想明白相机模型,成像原理(小孔成像)。 相机标定一共分为两个部分: (1)在进行精度较高的测量时,需要校正畸变即图像的畸变矫正 !(是自身的) (2)相机和机器人之间标定 =手眼标定!

相机标定:(2)内\外参矩阵和畸变矩阵

由(1)我们知道相机模型:相机标定:(1)相机模型_Upupup6的博客-CSDN博客 标定一共分为两个部分: (1)在进行精度较高的测量时,需要校正畸变即图像的畸变矫正,需要进行相机标定 !(是自身的) (2)相机和机器人之间标定 =手眼标定! 0、标定的意义 无论是在图像测…

OpenCV中的立体图像创建深度图

OpenCV中的立体图像创建深度图 1. 效果图2. 源码参考这篇博客将介绍如何从立体图像创建深度图。 1. 效果图 原图 VS 视差图效果如下: 可以看到结果受到高度噪音的污染。通过调整 numDisparities 和 blockSize 的值,可以获得更好的结果。 2. 源码 # 立体图像匹配和点云生…

OpenCV中的特征匹配+单应性以查找对象

OpenCV中的特征匹配+单应性以查找对象 1. 效果图2. 源码参考这篇博客将混合calib3d模块中的特征匹配和单应性,在复杂图像中查找已知对象。 1. 效果图 特征匹配 & 单应性查找对象效果图如下: 2. 源码 # 在图像中找到SIFT特征并应用比率测试来找到最佳匹配。import cv…

数字图像处理:边缘检测(Edge detection)

转载自:https://zhuanlan.zhihu.com/p/59640437 觉得写得通俗易懂,要是每个人的博客都这么人性化。。。。 写在前面: 本文篇幅较长,用了大量图与公式帮助大家深入理解各种边缘检测算子,希望大家能看完哈&#xff0c…

window对象提供的功能之窗口最大化

实现窗口最大化的基本思路是&#xff1a;首先打开一个“中转”页面&#xff0c;在该页面中用window.open方法打开一个最大化的窗口&#xff0c;并且在该窗口中将父窗口关闭。实例如下&#xff1a;ex3.html: 代码 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Trans…

Python,OpenCV中的K近邻(knn K-Nearest Neighbor)及改进版的K近邻

Python,OpenCV中的K近邻(knn K-Nearest Neighbor)及改进版的K近邻 1. 效果图2. 源码参考这篇博客将介绍将K-最近邻 (KNN K-Nearest Neighbor) 算法及改进版的K近邻,并演示如何根据K近邻进行简单的分类; KNN 是可用于监督学习的最简单的分类算法之一,是在特征空间中搜索测…

傅里叶分析

大佬致力于&#xff1a;要让读者在不看任何数学公式的情况下理解傅里叶分析。 傅里叶分析不仅仅是一个数学工具&#xff0c;更是一种可以彻底颠覆一个人以前世界观的思维模式。但不幸的是&#xff0c;傅里叶分析的公式看起来太复杂了&#xff0c;所以很多大一新生上来就懵圈并…