当前位置: 首页 > 编程日记 > 正文

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

.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

相关文章:

HTML5 3D旋转图片相册

H5旋转3D相册&#xff0c;鼠标放置暂停&#xff0c;图片灰度级为0&#xff0c;有放大效果。 该实例运用H5和CSS3动画效果&#xff0c;未用javascript。提高了本人对CSS3 新属性的了解及掌握。 完整代码如下&#xff1a; <!DOCTYPE html> <html lang"en">…

DHTML中style的display和visibility属性

DHTML中style的display和visibility属性 display是隐藏该对象&#xff0c;使该对象不占用页面排版空间。document.all("tr1").style.display"block"document.all("tr1").style.display"none" visibility只是在页面上看不见&#xff0c…

多线程共享全局变量以及锁机制

多线程都是在同一个进程中运行的。因此在进程中的全局变量所有线程都是共享的&#xff0c;这就造成一个问题&#xff0c;因为线程执行的顺序是无序的&#xff0c;有可能会造成数据错误&#xff0c;为了解决这个问题&#xff0c; threading提供了一个lock类&#xff0c;这个类可…

HTML DOM Console对象

在开发过程中对程序进行测试&#xff0c;经常使用浏览器控制台输出相关信息&#xff0c;下面详细介绍console对象的相关方法。 Console 对象 提供了访问浏览器调试模式的信息到控制台 1. console.assert()方法 用法&#xff1a;该方法在第一个参数为 false 的情况下会在控制台…

禁止拖放对象文本被选择

禁止拖放对象文本被选择的方法&#xff1a; 1.ie中设置拖放对象的onselectstart返回false&#xff0c;在ff中设置样式MozUserSelect(css:-moz-user-select)为none。 这种方法只能禁止拖放对象本身被选择。 2. ie:document.selection.empty() ff:window.getSelection().removeAl…

线性时间选择问题——分治

问题&#xff1a;求一个n个数的列表中第K个最小的元素。这个数字被称为第K个顺序统计量。问题求解&#xff1a; //对数组元素data[lowhigh]进行分区操作,0号单元不用intpartion(intdata[],intlow,inthigh){ data[0]data[low]; intpivotkeydata[low]; while(low<hig…

谷歌浏览器打不开设置等页面

问题描述 谷歌浏览器打不开任何页面&#xff0c;设置页面也打不开。卸载重装不起作用。 解决方案 方案1&#xff1a;添加启动参数 右击谷歌浏览器快捷方式图标&#xff0c;打开【属性】&#xff0c;在【目标(T)】输入框中追加参数-no-sandbox&#xff0c;即在下图中箭头所指…

Spring注解@Value

本文参考自: https://blog.csdn.net/ryelqy/article/details/77453713 Value能让我们在java代码中使用property文件的属性&#xff0c;使用Value有两种形式: 1、Value("#{configProperties[t1.msgname]}") 2、Value("${t1.msgname}") 这两种形式&#xff0…

201621123055《JAVA程序设计》第七周学习总结

1. 本周学习总结 1.1 思维导图&#xff1a;Java图形界面总结 1.2 可选&#xff1a;使用常规方法总结其他上课内容。 答&#xff1a;GUI监听器&#xff1a;一个事件监听器对象负责处理一类事件 一类事件的每一种发生情况,分别由事件监听器对象中的一个方法来具体处理. 在事件源和…

SQL Server 中print Datetime类型问题

declaredatedatetimesetdate2010-1-1printdateadd(dd,1,date)输出:01 2 2010 12:00AM 输出的是2010年1月2日 上午12:00 咦?那我就纳闷了,我要的是2010年1月2日 上午00:00:00 后发现原来print会将打印的数据类型隐式转换成字符串,所以就输出:01 2 2010 12:00AM这样的结果 我们…

iis上实现虚拟目录

有时候项目中需要 将引用相同的文件 可以再iis上建立虚拟目录 &#xff08;其实就是一个文件夹&#xff09; 比如 temp文件夹在另外的站点上 可以通过虚拟目录 将其引用进来&#xff01;

JavaScript判断对象是否为空对象或空数组

1. 判断一个变量是对象还是数组 首先判断一个变量是对象还是数组&#xff0c;不能使用typeof来判断&#xff0c;因为不管是对象还是数组&#xff0c;使用typeof得到的都是"object"。 可以使用Object.prototype.toString.call()方法。 function isObjOrArr(obj) {if …

python_2开发简单爬虫

2017年12月03日 16:43:01 独行侠的守望 阅读数&#xff1a;204 标签&#xff1a; python爬虫 更多个人分类&#xff1a; Python编辑版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请注明文章链接。 https://blog.csdn.net/xiaoanzi123/article/details/78700863学习地…

Mac下安装Node.js

1> brew install node 2> 查看版本&#xff1a; node --version 学习传送门&#xff1a; http://www.imooc.com/learn/637 菜鸟学习&#xff1a; http://www.runoob.com/nodejs/nodejs-http-server.html 官网&#xff1a;https://nodejs.org/zh-cn/ 转载于:https://www.…

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

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

Framework 4.0 新关键字dynamic 之我见(二)

Hi&#xff0c;大家好&#xff0c;随着大家对VS2010的深入了解&#xff0c;对dynamic已经是越来越了解了&#xff0c;何时该用&#xff0c;何时不用已经非常熟悉了&#xff0c;原本不打算再写下去的&#xff0c;但感觉还有点东西需要说说&#xff0c;就简单再说一下吧。 原先以…

JavaScript 数组排序及查找数组中最大值最小值方法

JavaScript 数组排序方法及查找最大值最小值方法1. sort()方法排序1.1 方法介绍1.2 语法&#xff1a;arr.sort([compareFunction])1.3 参数说明1.4 返回值&#xff1a; 排序后的数组。1.5 方法描述2. 最大值/最小值方法2.1 查找数组中的最大值2.1.1 Math.max.apply()方法语法&a…

35个必备的wordpress插件

博客一开始是自己写的小程序&#xff0c;但自己写程序实在太麻烦了&#xff0c;不想写&#xff0c;于是转成了bo-blog&#xff0c;用了几周&#xff0c;感觉还是不太理想&#xff0c;就又转换成了wordpress&#xff0c;这个博客程序也不是什么省油的灯&#xff0c;用起来也不是…

1042. 托普利兹矩阵

描述 “托普利兹矩阵”是指如果从左上角到右下角的同一条主斜线上每个元素都相等的矩阵. 给定一个M x N矩阵&#xff0c;判断是否为“托普利兹矩阵”. matrix 是一个二维整数数组.matrix 的行列范围都为 [1, 20].matrix[i][j] 的整数取值范围为[0, 99].样例 样例 1: 输入: matr…

git控制台指令

git stash: 备份当前的工作区的内容&#xff0c;从最近的一次提交中读取相关内容&#xff0c;让工作区保证和上次提交的内容一致。同时&#xff0c;将当前的工作区内容保存到Git栈中。git stash pop: 从Git栈中读取最近一次保存的内容&#xff0c;恢复工作区的相关内容。由于可…

Web架构师必备能力

最近和几个朋友在谈到时下流行的Web 2.0&#xff0c;也提到了其中最重要的角色——架构师。多方各有争执&#xff0c;不外乎是因为背景和视角的缘故&#xff0c;包括架构一词&#xff0c;本身就从建筑学借鉴而来&#xff0c;至于架构师&#xff0c;则可以简单地从建筑学的设计师…

深入理解C语言-二级指针三种内存模型

二级指针相对于一级指针&#xff0c;显得更难&#xff0c;难在于指针和数组的混合&#xff0c;定义不同类型的二级指针&#xff0c;在使用的时候有着很大的区别 第一种内存模型char *arr[] 若有如下定义 char *arr[] {"abc", "def", "ghi"};这种…

如何获取URL中的参数

获取URL中的参数1. 使用JS函数获取URL参数使用示例2. Angular应用中&#xff0c;从URL中获取参数信息的方法使用示例ActivatedRoute属性1. 使用JS函数获取URL参数 function getQueryVariable(variable) {var query window.location.search.substring(1);var vars query.spli…

windows使用.NET CORE下创建MVC,发布到linux运行

1.在有dotnet core 的环境下&#xff0c;打开控制台。创建文件夹demo1 2.创建MVC程序 3.创建完成 4.使用记事本修改一下HomeController 修改端口 5.发布 6.压缩发布的文件publish&#xff0c;通过FTP上传到linux 7.解压 8.运行 9.浏览器浏览 转载于:https://www.cnblogs.com/qq…

Oracle正则表达式匹配中文的问题

查资料知道中文Unicode范围是\u4e00 - \u9fa5 可是自己用来正则表达式匹配中文总是用不了Unicode。最简单举例&#xff1a;select regexp_replace(abc秋歌def,[\u4e00-\u9fa5],-) from dual;结果是&#xff1a;-bc秋歌d-- 即将\u4e00-\u9fa5里面的a,b,e,f当成字符了。我用的是O…

Oracle HowTo:如何使用Oracle case函数

通过实例简要介绍case函数的用法。1.创建测试表:DROP SEQUENCE student_sequence; CREATE SEQUENCE student_sequence START WITH 10000 INCREMENT BY 1; DROP TABLE students; CREATE TABLE students (id NUMBER(5) PRIMARY KEY,first_name VARCHAR2(20…

Attribute 绑定、类绑定和样式绑定

Attribute 绑定、类绑定和样式绑定 1. 绑定到 Attribute 优先设置带有 Property 绑定的元素的 Property。如果没有可绑定的元素 Property&#xff0c;可以使用 Attribute 绑定。 例如&#xff0c;ARIA和SVG 只有 Attribute。 ARIA 和 SVG 都不对应于元素的 Property&#xf…

Mixing Milk(USACO)

/* ID:tianlin2 PROG:milk LANG:C */ #include <iostream> #include <cstdlib> #include <fstream> using namespace std; typedef struct milk milk; struct milk{ int mon; int wei; }; //最大农民数 milk m[5000]; int moncmp(const void *va,const void …

DVWA的安装与简单使用

参考资料: http://www.freebuf.com/articles/web/119150.html 尝试使用linux机器安装,但是因为下载php版本以及各种兼容性的问题耗时较长, 所以后来选择使用windows server 来进行安装: 1. 下载xampp 版本尽量使用低一些的 比如 php版本在5.4 以下 能够更简单的入门学习. 2. 下…

CentOS安装中文输入法

安装中文语言支持 yum install "chinese support" 然后启动中文你语言输入法 system -->Preferences-->Input Method Enable input method feature Input Method Preferences Inout Method 转载于:https://www.cnblogs.com/browselife/p/10646256.html