将 dotNET组件暴露给COM (下)

原创 2002年08月07日 11:58:00
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

dotNET组件暴露给COM

 

小气的神

2002-4-23

 

Article Type: In-Depth 

难度等级:6/9       

版本:2.32

 

 

AutoDispatch参数产生的类型库描述:

  coclass dotNETClass {

        [default] interface _dotNETClass;

        interface _Object;

    };

 

    [

      odl,

      uuid(BCE3DFCD-F8F6-32F6-BB38-6F4928090805),

      hidden,

      dual,

      oleautomation,

      custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, COMVisible.dotNETClass)   

 

    ]

    interface _dotNETClass : IDispatch {

    };

None参数产生的类型库描述:

   coclass dotNETClass {

        [default] interface _Object;

    };

 

如果dotNET组件的客户是一个VB或需要双接口的Script型环境,那么我们最好的选择是: AutoDual.

否则我们就可能在VB下就真的会发生一开始讲的那些问题。

 

       至于第6点是有关注册的,如果你没有在VS.NET中设置自动注册,那么这个dotNET如果要暴露给COM,那么需要你手工注册。你可以在VS.NET中点击Solution Explorer中项目,然后右键中的属性,在配置页打开这个开关。如下图

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

 

 

我建议你完成所有的编码在第一次测试前打开这个开关。这个开关基本上和你的两个手工操作的功能相同,一个是regasm 组件.dll tlbexp 组件名 /out:Tlb文件名。如果自动方式VS.NET会自动UnRegasm和进行再注册,同时我们3-4步保证它不会编译一次产生一个新的GUID号而让你迷惑和担心搞乱你的注册表。

 

       不过如果我们可以改变我们原来的习惯的话,我们应该更多的使用Interface,而不是像原来一样去直接在VB中创建一个Class或组件。这样的方式可能更加优雅和健壮一些:

 

[GuidAttribute("ATC869A7-F101-4e7c-B062-CE56FDA5F678")]

public interface : IdotNETClass

{

       public int Add( int x, int y ) ;

       public int AddEx(intx , int y , int z ) ;

       public string Hello() ;

}

 

[GuidAttribute("08C869A7-F101-4e7c-B062-CE56FDA5F352")]

public class dotNETClass : IdotNETClass

{

       .................

}

 

精确定义类所遵循的接口是让你的同伴感到尊敬的一种设计和代码习惯,这样类倒出类型库时,所有的工具不必猜测类的定义。对于VS.NET这类有一些感知功能的IDE,不用太多的属性它都可以理解你的意图了。

 

下面是一些常用的COM互操作的支持属性,这些属性是CLR”Managed”类作为COM对象,暴露给非托管领域所必须的。这些信息大多在System.Runtime.Interopservices中可以找到。

 

属性

例子

适应范围

说明

ComVisible

[ComVisible(false)]

类,结构,接口,

委托,配件

决定生成的类型库中不需要暴露的CLR公共类型

DispID

[DispID(3)]

方法,属性

确定DispID,供IDispatch接口访问

ProgId

[ProgId(“dotNet.C”]

类所用的ProgID

Guid

[GuidAttribute(“xxx”)]

类,接口、模块

结构,枚举委托

指定COM GUID。写法上要小心和Guid类型冲突

InterfaceType

[InterfaceType(ComInterfaceType.InterfaceIsDual)]

接口

指定类型库生成任何一种COM的接口类型,比如:IUnknown

ComRegisterFunction

[ComUnregisterFunction()]

方法

请求Regasm.exe执行一个方法

HasDefaultInterface

MSDN Help

指定默认接口

NoIDispatch

MSDN Help

指示从IUnknown派生

MarshalAs

MarshalAs()

属性

定义列集

      

我不完全认为“dotNET可以完全取代以前COM的编程方式,但无法取代COM+”这样的结论一定正确或这样的时代已经来临,但的确目前dotNET提供的COM互操作的特性足够维持一个很好的兼容和互操作程度;如果你以前使用VBVC++进行COM的开发,那么现在你仍可以在dotNET平台上做同样的事情,有些微妙变化的是,在经历某个实践的曲线之后,你会发现dotNET平台下更方便和节省时间,当然你必须保证自己不是很介意性能,因为这种交互不可避免的需要以一些性能为代码。

 

好了最后我会举这样一个例子:在dotNET之前我们针对Biztalk Server的开发多是使用COM的方式,自从Biztalk Server 2002 Toolkit for Microsoft.NET的发布之后,你可以用dotNET做更多的一些工作。比如其中我们经常会编程开发的Application Integration Component(AIC),这些组件除了要实现一定接口之外,还必须要求我们登记到注册表的某个特定的Catalog ID下,用VC++ATL可以用BEGIN_CATEGORY_MAP 宏,但是其他的方式几乎都需要手动生产和完成注册步骤,Microost最后索性告诉你,对于AIC组件最简单的办法是把它们安装到COM+中,这样不仅不用注册而且还能提高性能。但如果我们知道上面的属性使用ComRegisterFunction/ComUnregisterFunction,就可以告诉Regasm.exe在注册时执行某个我们定义的方法来完成特定的注册,最大的发挥组件自描述的功能。在附带的例子中我们可以看到当我们在原来类实现的最后加上这样的代码:

 

[ComRegisterFunction()]

public static void RegisterFunction(Type t)

{

       try

       {

              // Implements CATID_BIZTALK_COMPONENT category

              Registry.ClassesRoot.CreateSubKey("CLSID//{" + t.GUID.ToString().ToUpper() + "}//Implemented Categories//{5C6C30E7-C66D-40E3-889D-08C5C3099E52}");

              // Implements CATID_BIZTALK_CUSTOM_PROCESS category

              Registry.ClassesRoot.CreateSubKey("CLSID//{" + t.GUID.ToString().ToUpper() + "}//Implemented Categories//{BD193E1D-D7DC-4B7C-B9D2-92AE0344C836}");

 

       }

       catch(Exception e )

       { throw new Exception( e.Message,e ); }

}

 

Regasm在注册时就会执行这段代码完成对特殊的Catalog的条目注册。

 

 

类似的情况还会很多比如SQL ServerVisioOffice 插件,Smart tags甚至AutoCAD for win等等许许多多支持COM接口的著名应用开发程序,你可以应用dotNET的互操作性来完成以前COM环境下的工作,并且工作在dotNET环境下,你可以从整个dotNET框架中获得一些以前平台所没有的好处,比如:命名空间、组件强名和多版本、密匙、自描述组件、线程模式等等,生产率可能是让你感到最愉悦的:) 当你跨越了为什么要使用dotNET组件而将焦点放在如何将dotNET组件暴露给COM以及有效的做到这一点时,我想,这种思考和实践本身会给你带来许多不同的体验和好处。

 

       以上我们简单的考察了dotNET和互操作的一些最基本和常用的方法,在使用dotNET和向dotNET迁移的过程中我们会发现,对于dotNET调用COM组件或是COM应用调用dotNET组件的情况会逐渐减少,但可能很长一段时间还都会存在,越来越多的情况是dotNETdotNET的“Managed”环境,互操作只是为了最好的兼容性,不过如果你十分喜欢和难以忘怀诸如晚绑定这样的迷人特性,那么充分使用这种互操作将是必须的。好的互操作使得我们可以有更多的选择,也可以保留我们喜欢的特性,一半COM一半dotNET的架构,保证平滑的迁移。但象上面所述的那样,或许某种情境下互操作可能变成你唯一的选择或是一条必经之路:)

 

相关文件下载: [COMVisible.zip 29K ]

 

特别:

本文原创,CSDN署名首发,所有文字和图片版权所有。未经授权请勿传播、转载或改编。

如果有问题或建议,请发电子邮件给new2001@msn.com

dotnet 下开发 COM+ 组件

转载:一、问题的提出    1、最终用户的每次请求,都将读取Mapping文件——可以通过缓存解决;    2、xxx子系统需要不断的写入Mapping文件——也可以先写入内存然后批量写入文件解决; ...
  • Jeelo
  • Jeelo
  • 2006年08月01日 20:47
  • 800

VC调用COM组件的几种方法

这篇的内容也是我在使用COM组件的时候遇到困难后在网上找的一些调用的方法,以备后用。 1.首先创建一个COM组件:myCom.ocx    组件里面有一个普通接口:ImyCom   一个方法为:Hel...
  • u013823973
  • u013823973
  • 2014年12月26日 14:42
  • 1843

启动COM组件的三种机制

这里的COM组件可以是一个进程内服务器(In-Process Server),也可以是一个进程外服务器(Out-Of-Process Server)。一般情况下,我们在使用这些COM组件的时候,只要保...
  • sunnylion1982
  • sunnylion1982
  • 2013年11月21日 17:24
  • 2080

COM组件入门(一)

最近需要用到COM组件的知识,看了看COM编程指南,感觉还不错,把我的学习心得记录下来。这是我写...
  • davidsu33
  • davidsu33
  • 2014年08月13日 17:08
  • 1175

C++ COM组件编写初探

最近在学习COM,自己实现了一个小Demo,拿出来和大家分享一下。求各种批评。 我实现的这个组件向外提供了一个接口ICompTest,里面只有一个函数helloworld(),功能为返回一个整数...
  • shejiannan
  • shejiannan
  • 2014年05月20日 17:41
  • 851

一份完整的com组件服务端和客户端教程

最近在学com组件编程 苦于没有没有好的完整的教程 浪费大把时间,尤其是连接点那一块 ,网上很多文章都是 只显示代码的一段,本文更注重 项目的配置,完整如下 参考文章:              ...
  • wujinzbr
  • wujinzbr
  • 2015年04月16日 16:12
  • 487

Excel操控方法之Com组件

使用微软官方Com组件Microsoft.Office.Interop.Excel对Excel进行操控,实现数据的读写,单元格背景颜色的修改等操作...
  • AdairXY
  • AdairXY
  • 2016年07月07日 10:44
  • 1362

COM组件开发(四)——VC++调用COM组件的方法

ActiveX 控件          对于ActiveX控件,可以在Visual Studio中使用ClassWizard的方法引入,在MFC项目中选择菜单“项目”——> “添加类”——>“Acti...
  • q5806622
  • q5806622
  • 2015年02月16日 15:15
  • 8106

Android静态安全检测 -> Service组件暴露

Service组件暴露 - exported属性 1. android:exported 该属性用来标示,其他应用的组件是否可以唤醒Service或者和这个Service进行交互 true ...
  • u013107656
  • u013107656
  • 2016年07月12日 17:52
  • 2505

COM技术内幕学习笔记---第八章---组件复用:包容和聚合

COM 不支持实现继承的原因在于这种继承方式将 使得一个对象的实现同另外一个对象的实现紧紧地关联起来。 在这种情况下,当基类的实现被修改之后,派生类将无法正常运行而必须被修改。对于一个中等规模的C+...
  • shb8845369
  • shb8845369
  • 2014年04月08日 15:06
  • 1312
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:将 dotNET组件暴露给COM (下)
举报原因:
原因补充:

(最多只允许输入30个字)