我想在所有现有方法不变的情况下向COM接口添加一个新方法,这会在更新之前破坏它与使用者的兼容性吗?
这取决于:如果这是一个内部未发布的接口,只要你控制了与该接口交互的所有代码,你就可以随意更改它。
然而,一旦发布,规则就很严格:每个接口都有自己的IID。您可以通过任何方式更改该接口——通过修改、添加或删除方法——它是一个全新的接口,需要一个新的IID。
然而:COM并不关心新接口是如何实现的:因此,您可以让您的类将其实现为只添加新方法的旧接口的派生,并让您的实现类实现该派生,只要QI在请求旧接口或新接口时返回合适的接口。
例如:
class IInterfaceOriginal: public IUnknown
{
public:
...
// lots of methods
...
};
class IInterfaceUpdated: public IInterfaceOriginal
{
public:
// Add just one additional method
STDMETHOD(AdditionalMethod)(...) = 0;
};
class CImplementation: IInterfaceNew // this was IInterfaceOld
{
// Also add implemention of AdditionalMethod somewhere here...
HRESULT STDMETHODCALLETYPE QueryInterface( REFIID riid, void **ppvObject )
{
*ppvObject = NULL;
if(riid == __uuidof(IUnknown)
|| riid == __uuidof(IInterfaceOriginal)
|| riid == __uuidof(IInterfaceUpdated)) // This is added
{
// Return a IInterfaceUpdated in response to a QI for either of IUnknown,
// or the old or new interface. This works because in C++, any IInterfaceUpdaed
// is also both of those two other interfaces.
*ppvObject = static_cast<IInterfaceUpdated*>(this);
}
else
return E_UNKNOWN;
return ((IUnknown*)*ppvObject)->AddRef();
}
...
}
因此,当你在技术上"添加另一个接口"时,你实际上在这里添加了一些代码:只需定义一个从旧接口派生的新接口,将类实现的接口更改为新接口(并为新方法添加实现),最后更新QI以支持旧方法和新方法——为两者返回相同的接口(也为IUnknown返回相同的界面)。
它肯定会破坏派生接口,所以即使看起来有效,也不应该这样做。
相反,派生一个包含附加方法的新接口,并具有需要新IID的附加功能QI的客户端。
只要附加了新方法,COM接口就应该向后兼容。如果客户端应用程序想要使用新的COM接口,则必须更新头文件(C++)或重新添加对新COM接口的引用(.NET)。此外,如果COM接口在未更新IID的情况下发生更改,则可能需要重新启动操作系统。总之,在不改变IID的情况下,它会起作用,但改变IID可能更"正确"。