.net调用com组件主要分为两类:静态调用及动态调用。
所谓静态调用:指通过通过tlbimp.exe命名产生com组件在.net环境下的包装类,然后通过这个包装类来访问com组件。
所谓动态调用:是指不通过com组件的包装类来进行com组件调用,而是在远行时通过反射来进行com组件调用。
下面将分别详细的讨论这两种实现方法:
<!--[if !supportlists]-->1、 <!--[endif]-->编写com组件mycomponent.dll
<!--[if !supportlists]-->2、 <!--[endif]-->产生可访问com组件的包装类:
tlbimp /out:interop.mycomponent.dll mycomponent.dll
<!--[if !supportlists]-->3、 <!--[endif]-->在.net代码中访问
只要在项目添加com包装类,就可以像访问.net的装配件一样访问com组件。
当然上面的三个步骤也可以在vs中直接添加对com组件的引用,让vs自动完成第二步。
注意:
<!--[if !supportlists]-->1、 <!--[endif]-->如果引用com组件的.net项目为结果为强命名组件,这个时候要求com组件的包装类也必须为强命名组件,所以这个时候必须手动进行第二步操作,并且在产生包装类的时候设置snk文件名称,具体操作方法为:
tblimp /keyfile:filename.snk /out:interop.mycomponent.dll mycomponent.dll
<!--[if !supportlists]-->2、 <!--[endif]-->要想有更多的设置请参考tlbimp的使用方法。
<!--[if !supportlists]-->1、 <!--[endif]-->编写com组件mycomponent.dll。
<!--[if !supportlists]-->2、 <!--[endif]-->在.net程序中产生要被调用的com组件类的type:
type comtype = type.gettypefromclsid( guid ); 或
type comtype = type.gettypefromprogid( string );
<!--[if !supportlists]-->3、 <!--[endif]-->生成com组件类对象
object comobj = activator.createinstance( comtype ); 或
object comobj = comtype.invokemember(
null,
bindingflags.declaredonly
bindingflags.public bindingflags.nonpublic
bindingflags.instance bindingflags.createinstance,
null, null, args );
<!--[if !supportlists]-->4、 <!--[endif]-->设置参数及其对应的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)。
<!--[if !supportlists]-->5、 <!--[endif]-->调用com组件方法或者属性。
object returnvalue = comtype.invokemember(
“methodname” ,
bindingflags.invokemethod… ,
null ,
comobj ,
args ,
modifiers ,
null );
注意:
<!--[if !supportlists]-->1、 <!--[endif]-->调用com组件方法的时候,不能够采用methodinfo的方式进行调用,由于没有com组件的源数据信息,不能通过type.getmethod等方法够获取与com组件相关的任何特有类型信息。
<!--[if !supportlists]-->2、 <!--[endif]-->动态调用com组件方法中,如果需要参数回传值,则必须将该参数对应的parametermodifier表示设置为true,即使该参数类型为传址类型。(在.net中如果参数为传址类类型,那么参数默认行为是byref的)。
<!--[if !supportlists]-->3、 <!--[endif]-->如果传递给com组件的参数设置为传引用的(parametermodifier[n] = true)的时候,该参数的值不能够为空(null),否则会产生一个targetinvocationexception异常。解决的方法为,如果参数为基本类型(传值)则产生一个默认的值,如果参数为非基本类型(传址)则使用new unknownwrapper(null)进行替代该参数。
具体步骤演示如下:
<!--[if !supportlists]-->1、 <!--[endif]-->定义接口:
com是通过抛出接口让外部应用调用的,每个接口、组件都有一个guid,在.net中开发com组件也不例外。
[guid(“0bb13346-7e9d-4aba-9ff2-862exml:namespace prefix = st1 />
public interface imyservice
{
//定义接口方法或者属性
//每个方法都有一个dispid属性,供vbscript等使用
[dispid( 1 )]
void method1( args … );
}
<!--[if !supportlists]-->2、 <!--[endif]-->实现接口的派生类
//progid定义com组件的progid
[guid( "ba
progid("classnamespace.myservice"),
classinterface( classinterfacetype.none)]
public class myservice : imyservice
{
…… //实现代码部分
}
<!--[if !supportlists]-->3、 <!--[endif]-->将.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对象必须具有下面的特性:
<!--[if !supportlists]-->l <!--[endif]-->类必须是public性质;
<!--[if !supportlists]-->l <!--[endif]-->特性、方法和事件必须是public性质的;
<!--[if !supportlists]-->l <!--[endif]-->特性和方法必须在类接口中定义;
<!--[if !supportlists]-->l <!--[endif]-->事件必须在事件接口中定义。
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器