Com与.Net互操作(二次业务开发及插件开发总结)

Com 与 .Net 互操作

一、 .Net 调用 Com 组件

.Net 调用 Com 组件主要分为两类:静态调用及动态调用。

所谓静态调用:指通过通过 tlbimp.exe 命名产生 Com 组件在 .Net 环境下的包装类,然后通过这个包装类来访问 Com 组件。

所谓动态调用:是指不通过 Com 组件的包装类来进行 Com 组件调用,而是在远行时通过反射来进行 Com 组件调用。

下面将分别详细的讨论这两种实现方法:

² 静态调用

1、 编写 Com 组件 MyComponent.dll

2、 产生可访问 Com 组件的包装类:

tlbimp /out:Interop.MyComponent.dll MyComponent.dll

3、 在 .Net 代码中访问

只要在项目添加 Com 包装类,就可以像访问 .Net 的装配件一样访问 Com 组件。

当然上面的三个步骤也可以在 VS 中直接添加对 Com 组件的引用,让 VS 自动完成第二步。

** 注意: **

1、 如果引用 Com 组件的 .Net 项目为结果为强命名组件,这个时候要求 Com 组件的包装类也必须为强命名组件,所以这个时候必须手动进行第二步操作,并且在产生包装类的时候设置 snk 文件名称,具体操作方法为:

tblimp /keyfile:filename.snk /out:Interop.MyComponent.dll MyComponent.dll

2、 要想有更多的设置请参考 tlbimp 的使用方法。

² 动态调用

1、 编写 Com 组件 MyComponent.dll 。

2、 在 .Net 程序中产生要被调用的 Com 组件类的 Type :

Type comType = Type.GetTypeFromCLSID( Guid ); 或

Type comType = Type.GetTypeFromProgID( string );

3、 生成 Com 组件类对象

object comObj = Activator.CreateInstance( comType ); 或

object comObj = comType.InvokeMember(

null,

BindingFlags.DeclaredOnly |

BindingFlags.Public | BindingFlags.NonPublic |

BindingFlags.Instance | BindingFlags.CreateInstance,

null, null, args );

4、 设置参数及其对应的 ByRef 属性。

object[] args = new object[]{arg1, arg2 , …,argn};

ParameterModifier[] modifiers = new ParameterModifier[1];

modifiers[0] = new ParameterModifier( argNumCount );

// 设置参数是否为 ByRef

modifiers[0][0] = true;// 表示该参数是 ByRef ( InOut/Out )

modifiers[0][n] = false;// 表示该参数是 ByValue ( In )。

5、 调用 Com 组件方法或者属性。

object returnValue = comType.InvokeMember(

“MethodName” ,

BindingFlags.InvokeMethod|… ,

null ,

comObj ,

args ,

modifiers ,

null );

** 注意: **

1、 调用 Com 组件方法的时候,不能够采用 MethodInfo 的方式进行调用,由于没有 Com 组件的源数据信息,不能通过 Type.GetMethod 等方法够获取与 Com 组件相关的任何特有类型信息。

2、 动态调用 Com 组件方法中,如果需要参数回传值,则必须将该参数对应的 ParameterModifier 表示设置为 True ,即使该参数类型为传址类型。 (在 .net 中如果参数为传址 类类型,那么参数默认行为是ByRef的)。

3、 如果传递给 Com 组件的参数设置为传引用的( ParameterModifier[n] = true )的时候,该参数的值不能够为空( Null) ,否则会产生一个 TargetInvocationException 异常。 解决的方法为,如果参数为基本类型(传值)则产生一个默认的值,如果参数为非基本类型(传址)则使用 new UnknownWrapper(null) 进行替代该参数。

二、 Com 调用 .Net 组件

具体步骤演示如下:

1、 定义接口:

Com 是通过抛出接口让外部应用调用的,每个接口、组件都有一个 Guid ,在 .Net 中开发 Com 组件也不例外。

[Guid(“0bb13346-7e9d-4aba-9ff2-862e 0105489a ”)]

public interface IMyService

{

// 定义接口方法或者属性

// 每个方法都有一个 DISPID 属性,供 VBScript 等使用

[DispId( 1 )]

void Method1( args … );

}

2、 实现接口的派生类

//guid 属性定义组件的 Guid

//ProgID 定义 Com 组件的 ProgID

[Guid( "ba 0a 3019-f0d8-4406-8116-f80d 5515c 686" ) ,

ProgId("ClassNamespace.MyService"),

ClassInterface( ClassInterfaceType.None)]

public class MyService : IMyService

{

…… // 实现代码部分

}

3、 将 .Net 装配件转换为公有装配件。

(1) 、创建强名字

sn –k MyService.snk

并将强名字拷贝到工程目录下面

在 AssembyInfo.cs 修改对应的配置

[assembly: AssemblyKeyFile(@“../../MyService.snk”)]

(2) 、注册装配件

RegAsm /codebase MyService.dll

** 注意 ** : /codebase 是指设置注册表中的基本代码,也就是记录下 dll 的路径,供 ccw 在 Com 客户端在任何位置都可以找到该 dll ,如果没有 /codebase 属性,则 ccw 默认为 dll 与 Com 客户端执行程序的当前目录下面。

( 3 )、将装配件加入 GAC

gacutil -i MyService.dll

** 注意: ** 该步骤不是必须的。

( 4 )、导出类型库

为了在 VB 中使用,必须使用 tlbexp.exe 导出 Com 类型库。

tlbexp /out:MyService.tlb MyService.dll

经过上面的工作,就将一个 .NET 装配件转化为 COM 组件。

** ** ** 注意: **

** ** 在 Com 中调用的 .Net 对象必须具有下面的特性:

l 类必须是 public 性质 ;

l 特性、方法和事件必须是 public 性质的 ;

l 特性和方法必须在类接口中定义 ;

l 事件必须在事件接口中定义。

Published At
Categories with Web编程
Tagged with
comments powered by Disqus