.NET组件 vs. COM组件
本文转载:https://www.cnblogs.com/larissa-0464/p/11095203.html
写在前面:我没有开发过COM组件的经验,只是在做文献综述的时候需要了解这方面的知识,所以如果哪里说错了或者是我理解错了,还希望大家可以指出,谢谢。我不是程序员也不是计算机专业,只是课题偏了这个方向,因此很多基础概念或许有理解错,真心希望可以得到大家的指正,再次感谢。
COM object以接口的方式向客户端提供服务。一个COM component可以包含多个COM object,一个COM object可以有多个接口,其关系如图1所示。
图1 COM组件、COM对象和接口关系
在Windows OS上,COM组件以.dll或者.exe的文件形式存在。其中.dll是进程内组件(in-process component),.exe是进程外组件(out-process component)。进程内组件意味着该组件会被加载到客户端所在的进程中,而进程外组件则意味着该组件会被加载到一个新的进程中。
二进制接口是COM组件中的重要概念,正是因为存在binary interface compatibility, 组件的开发语言不受限制,不一定非得是C/C++。接口是用Microsoft Interface Definition Language (MIDL)描述的。每个接口有唯一标识,使用IID(interface identifier)命名。接口都需要继承自IUnknown接口,该接口提供了对接口的生存期控制和接口查询。下面是一个用MIDL描述的接口的例子:
interface IWithdraw : IUnknown
{
HRESULT Withdraw([in] Bank bank, [in] Integer amount, [out, retval] int* balance);
};
每个COM object也有一个唯一标识,用CLSID表示。客户端通过COM库和类厂成功创建了对象的实例后,会得到一个指向COM object某个接口的指针(pointer),该指针实际上又指向了另一个指针(interface pointer),第二个指针指向一组函数,称为接口函数表或虚函数表(virtual table pointer),如图2所示。
图2 接口结构
COM component使用前需要先注册。组件程序把它所实现的COM object的信息以及接口信息都保存在注册表中,然后COM库通过系统注册表所提供的信息进行组件的创建工作。
在组件的创建工作中,还需要用到类厂(class factory)。类厂本身也是一个COM object,它支持一个特殊的接口IClassFactory,其定义如下:
class IClassFactory : public IUnknown
{
virtual HRESULT_stdcall CreateInstance(IUnknown *pUnknownOuter, const IID&iid, void**ppv) = 0;
virtual HRESULT_stdcall LockServer(BOOL bLock) = 0;
};
其中,CreateInstance用于创建对应的COM对象。那么,客户端创建COM对象的过程就应该是:
- 客户端调用COM库中CoCreateInstance函数或者CoGetClassObject函数
- COM库从注册表中找到相应的DLL程序并载入到进程中
- 调用组件程序中DllGetClassObject函数,创建类厂,并把类厂接口指针返回给CoGetClassObject函数或者CoCreateInstance函数
- 然后创建类厂对象,进而类厂创建COM对象,类厂把COM对象返回给CoGetClassObject函数或者CoCreateInstance函数,最后客户端可以直接调用COM对象。
COM组件支持两种方式的重用,分别是包容(containment/delegation)和聚合(aggregation),如图3所示。
a) containment
b) aggregation
图3 COM组件的两种重用方法
Containment。对象A包含在对象B中,客户端想要调用对象A中的方法时,需要通过对象B来调用。
Aggregation。对象A的接口暴露在对象B的外面。当客户端想要调用对象A中的方法时,直接调用。但是客户端并不知道对象A的存在。
.NET中使用的是程序集(assembly)这个概念。使用C#编写的程序编译后成为程序集(.dll或者.exe格式的文件)。程序集的组成如图4所示。
图4 程序集的组成
其中,程序集列表是必须有的(assembly manifest)。程序集列表包括该程序集元数据,例如与指定程序集版本要求、安全标识所需的所有元数据,以及定义程序集范围和解析对资源和类的引用所需的所有元数据。
程序集列表中的内容包括:
assembly name、version number、culture、strong name information (这四项组成了程序集的标识)、list of all files in the assembly、type reference information、information on referenced assemblies
https://docs.microsoft.com/en-us/dotnet/framework/app-domains/assembly-manifest
程序集中无需使用IDL文件来定义组件接口的信息,取而代之的是元数据(metadata)。元数据包括程序集的一切基本信息,比如版本、类型、命名空间、依赖的其他程序集信息等。一个.dll文件中的元数据信息可以通过reflection获取(包括命名空间、类、属性、方法等)。编译器会自动地把程序中的这些相关信息封装在程序集的元数据中。因此,可以说程序集是一种自描述的组件。元数据的使用也使得程序集无需像COM组件,在使用前需要注册。详情可见:
https://docs.microsoft.com/en-us/dotnet/standard/metadata-and-self-describing-components
MSIL code是指程序集会首先被编译成一种微软中间语言(Microsoft Intermediate Language),程序无论是用C#写还是VB写,编译成IL都是等效的。.NET平台是建立在CLR(Common Language Runtime)基础上的,也就是说用C#写的程序要经历过两次译码才能在机器上运行,这与C++是不一样的。第一次译码是转换成IL,第二次才是转换成与操作系统相匹配的二进制指令。第二次是CLR负责的。这样运行在CLR基础上的被称为托管代码,而COM组件则是用非托管代码实现的。
resources就是指程序集包含的一些可用资源,这些资源在程序集运行时是可以使用的,包括字符串、图片以及特殊文件等。
因此,.NET组件(assembly)与COM组件相比具有自描述、自包含的特点。其在使用时无需注册,在创建时也无需使用COM库和类工厂,接口定义和实现也不是分开的。
COM组件的二进制兼容性是通过使用接口指针和虚函数表实现的,而.NET组件的二进制兼容性是通过使用元数据实现的。
.NET组件 vs. COM组件的更多相关文章
- 谈谈我对前端组件化中“组件”的理解,顺带写个Vue与React的demo
前言 前端已经过了单兵作战的时代了,现在一个稍微复杂一点的项目都需要几个人协同开发,一个战略级别的APP的话分工会更细,比如携程: 携程app = 机票频道 + 酒店频道 + 旅游频道 + ..... ...
- BenUtils组件和DbUtils组件
BenUtils组件和DbUtils组件 [TOC] 1.BenUtils组件 1.1.简介 程序中对javabean的操作很频繁,所有Apache提供了一套开源api,方便javabean的操作!即 ...
- JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐(二)
前言:上篇 JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐 分享了几个项目中比较常用的组件,引起了许多园友的关注.这篇还是继续,因为博主觉得还有几个非常简单.实用的组件,实在不愿自己 ...
- JS组件系列——表格组件神器:bootstrap table
前言:之前一直在忙着各种什么效果,殊不知最基础的Bootstrap Table用法都没有涉及,罪过,罪过.今天补起来吧.上午博主由零开始自己从头到尾使用了一遍Bootstrap Table ,遇到不少 ...
- JS组件系列——表格组件神器:bootstrap table(二:父子表和行列调序)
前言:上篇 JS组件系列——表格组件神器:bootstrap table 简单介绍了下Bootstrap Table的基础用法,没想到讨论还挺热烈的.有园友在评论中提到了父子表的用法,今天就结合Boo ...
- JS组件系列——表格组件神器:bootstrap table(三:终结篇,最后的干货福利)
前言:前面介绍了两篇关于bootstrap table的基础用法,这章我们继续来看看它比较常用的一些功能,来个终结篇吧,毛爷爷告诉我们做事要有始有终~~bootstrap table这东西要想所有功能 ...
- WPF中实例化Com组件,调用组件的方法时报System.Windows.Forms.AxHost+InvalidActiveXStateException的异常
WPF中实例化Com组件,调用组件的方法时报System.Windows.Forms.AxHost+InvalidActiveXStateException的异常 在wpf中封装Com组件时,调用组件 ...
- react native 之子组件和父组件之间的通信
react native开发中,为了封装性经常需要自定义组件,这样就会出现父组件和子组件,那么怎么在父组件和子组件之间相互通信呢,也就是怎么在各自界面push和pop.传值. 父组件传递给子组件: 父 ...
- vuejs动态组件给子组件传递数据
vuejs动态组件给子组件传递数据 通过子组件定义时候的props可以支持父组件给子组件传递数据,这些定义的props在子组件的标签中使用绑定属性即可,但是如果使用的是<component> ...
- [js开源组件开发]query组件,获取url参数和form表单json格式
query组件,获取url参数和form表单json格式 距离上次的组件[js开源组件开发]ajax分页组件一转眼过去了近二十天,或许我一周一组件的承诺有了质疑声,但其实我一直在做,只是没人看到……, ...
随机推荐
- Spring Boot 3.0.0 发布第一个里程碑版本M1,你的 Java 升到17 了吗?
2022年1月20日,Spring官方发布了Spring Boot 3.0.0的第一个里程碑版本M1. 下面一起来来看看Spring Boot 3.0.0 M1版本都有哪些重大变化: Java基线从 ...
- django-环境搭建-开使hello world!
django的环境安装非常简单,只需用pip安装一个django库就可以了,编辑器选择pycharm pip install django==2.1.2 查看版本号:pip show django C ...
- IDEA构建Maven项目过慢的解决方法
创建Maven项目时在此页面添加 archetypeCatalog internal 即可
- Kubernetes集群PV和PVC详解
Kubernetes集群高级存储资源PV及PVC 文章目录 Kubernetes集群高级存储资源PV及PVC 1.高级存储PV和PVC概念部分 2.PV和PVC资源的生命周期 3.PV资源介绍与案例配 ...
- 如何在 VS Code 中为 Java 类生成序列化版本号
前言 IDEA 提供自动生成序列化版本号的功能,其实 VS Code 也可以,只是默认关闭了这个功能,下面就来看看如何开启这个功能吧. 配置过程 首先需要保证 VS Code 上安装了提供 Java ...
- springboot实战小项目-简要介绍、vue项目创建
因为菜,所以要好好学习! 一.项目介绍:这是一个后台管理系统,准备实现的功能: 1.登录.注册.个人信息查看.退出登录 2.根据关键字查询用户.新增用户.根据id或者其他字段排序.编辑用户信息.删除用 ...
- X000101
P3879 [TJOI2010]阅读理解 考虑用 Trie 解决 #include<stdio.h> #include<bitset> #include<string.h ...
- Td 内容不换行,超过部分自动截断,用...表示
转载请注明来源:https://www.cnblogs.com/hookjc/ <table width="200px" style="table-layout:f ...
- Linux常用命令精华讲解 上部 (下部下回分解)不要催很忙的
Linux常用命令讲解 1.Linux命令基础 2.Linux命令帮助 3.目录与文件的基操 1.Shell是系统中运行的一种特殊程序在用户和内核之间充当"翻译官"的角色,登录li ...
- MySQL时间格式TIMESTAMP和DATETIME的区别
时区,timestamp会跟随设置的时区变化而变化,而datetime保存的是绝对值不会变化 自动更新,insert.update数据时,可以设置timestamp列自动以当前时间(CURRENT_T ...