COM+ 1.5可以说是Indigo到来之前的暂时替代产品,COM+ Service基本上也都是Unmanaged Code,就像MSDN Magazine里面的一篇文章说的那样,COM+是:
complex architecture where there are numerous places where the managed code interacts with unmanaged code - some documented, others undocumented.
问题的症状是这样的:装载一个继承自定义接口的、Server方式激活的COM+ 组件时抛出这样的异常,或者提示“XXX接口没有实现”。
可以说COM+里面80%莫名其妙的错误都是和COM InterOp有关,这个问题也不例外。如果把组件的激活方式改成Library就一切正常了,原因就在于进程内Enterprise Component使用Managed C++ Assembly直接调用COM+ API,而进程外的Enterprise Component则是使用RCW (Runtime Call Wrapper)来实现同COM+ API的Interop,问题也就出在InterOp上面。
首先一个问题,COM+ Component是可能被Unmanaged Client调用的,为了支持这种调用,我们通过指定[ClassInterface(ClassInterfaceType.AutoDispatch)],生成支持IDispath的Class Interface,这样做虽然无法支持Early Binding,但是能很好地避免因为Interface方法删改之后改变了Layout而导致Unmanaged Client无法正常工作。关于这方面的更多信息可以参考.NET Framework Document里面的Introducing to the Class Interface主题。
其次,为了保证继承的自定义接口是可以正常导出(tlbexp.exe)的,还需要指定接口生成的Class Interface的方式,缺省是生成Dual Interface,但为了和COM+ Component的接口生成方式相适应,还需要加上[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)],告诉tlbexp.exe这个接口将以IDispatch的方式生成。
代码看起来像这样:
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
public intface IFoo
{
void foo();
}
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[Transaction(TransactionOption.Required)]
public FooCOM : ServicedComponent, IFoo
{
..............
}
通过这样的设定,基本上解决了这个问题。