ECOM介绍

ECOM架构

ECOM是一个通用的、可扩展的框架,它可以定义抽象接口,并且可以识别接口的实现,还负责装载并管理它们。该框架:
可以识别所有特定接口的具体实现。
允许接口的客户动态指定应该使用哪一个接口实现。这个选择的过程被称为决议(resolution)。ECOM提供了一个默认的决议者,在需要的地方,接口定义可以提供它们自己自定义的决议者。
通过调用恰当的工厂函数(factory function)来实例化实现了接口的具体类的实例。

ECOM使用了客户机/服务器架构,ECOM客户类REComSession提供函数来列出、实例化以及销毁接口的实现。每个线程都存在一个单独ECOM客户会话实例,并且它可以被接口的实例化和析构代码所访问,这些代码使用了一组静态函数。

一个由ECOM插件实现的接口有两个特征,第一,它是一个定义了一组包含一个或多个纯虚函数的抽象类,第二,接口还必须提供一个或多个工厂方法,从而可以是客户实例化接口的实现对象。

工厂方法不会直接实例化对象,因为一个接口无法预测究竟哪个类实现了它。相反,工厂函数会将请求交给ECOM框架,而由框架在运行时动态地实例化恰当的实现类。为了决定实例化哪个实现,ECOM需要获得一点提示,这个提示可以是UID,也可以是文本,它们将被传递给决议者。还有一种情况是将特定接口所有实现的列表返回给调用者,再由调用者决定使用哪个实现。

 

ECOM接口的特性

* 接口将定义一组纯虚函数,它们将在具体实例中实现
* 接口必须提供一个或多个工厂函数,这些函数向ECOM传递信息,使其可以从正确的实现类实例化出对象
* 接口还必须为其客户提供释放方法,诸如析构函数可以使其被销毁,或者是诸如Release()或Close()之类的方法
* 一个ECOM接口定义还必须具有一个TUid数据成员,该成员由ECOM内部使用,出于清除的目的以此来标识实现类的实例

以下示例之,

class CCryptoInterface : public CBase
{
public:
    enum TAlgorithm { EDES, E3DES, EAES, ERC2, ERC4 };

     // 该类型的缺省对象实例化
     IMPORT_C static CCryptoInterface* NewL();

     // 实例化,通过aCue来指定使用哪个实现
     IMPORT_C static CCryptoInterface* NewL(const TDesC8& aCue);

     IMPORT_C virtual ~CCryptoInterface();

     // 列出该接口的所有实现
     IMPORT_C static void ListImplementionsL(RImplInfoPtrArray& aImplInfoArray);

public:
    // 需要由具体实例来实现的接口函数
     virtual void EncryptL(TDesC8& aPlaintext, TDesC8& aKey, TDes8& aCiphertext, CryptoInterface::TAlgorithm) = 0;
    virtual void DecryptL(TDesC8& aCiphrtext, TDesC8& aKey, TDes8& aPlaintext, CryptoInterface::TAlgorithm) = 0;

private:
     TUid iDtor_ID_Key; // 在清除中使用的标识符
};

工厂方法

不接受参数的NewL()重载形式会创建CCryphtoInterface默认实现的对象,有两种方法决定创建的默认实现,一是通过向ECOM传递UID来硬编码一个特定实现;另一中方法具有更松的耦合性,使用ECOM决议者,向决议者传递一些信息,使其能够进行实例化。例如,实例化它发现的第一个实现了接口的具体类。
第一种方法:
EXPORT_C CCryptoInterface* CCryptoInterface::NewL()
{
     // 硬编码以在默认情况下使用CCryptoInterface
     const TUid KSWCryptoUid = { 0x10008EE5 };

     TAny* defaultCrypto = REComSession::CreateImplementationL(KSWCryptoUid, _FOFF(CCryptoInterface, iDtor_ID_Key));

    return (reinterpret_cast<CCryptoInterface*>(defaultCrypto);
}

第二种方法接受一个参数,该方法会将参数传递给默认的ECOM决议者。决议者使用该参数,通过与接口注册实现的默认数据属性进行匹配,从而决定实例化哪个实现的具体实例。
// CCryptoInterface的接口UID
const TUid KCCryptoInterfaceUid = { 0x10008EE0 };
EXPORT_C CCryptoInterface* CCryptoInterface::NewL(const TDesC8& aCue)
{
    // 使用默认ECOM决议者的决议
    TEComResolverParams resolverParams;
    resolverParams.SetDataType(aCue);
    // 允许在字符串匹配中使用通配符
    resolverParams.SetWildcardMatch(ETrue);

    TAny* cryptoInterface = REComSession::CreateImplementationL(KSWCryptoUid, _FOFF(CCryptoInterface, iDtor_ID_Key), NULL, resolverParams);

    return (reinterpret_cast<CCryptoInterface*>(cryptoInterface);
}
第三个参数可以用于向具体类的初始化方法传递数据。如果CreateImplementationL()根据给出的提示找不到恰当的接口实现,它就会以KErrNotFound异常退出。

REComSession提供了一个ListImplementationsL()函数,该函数返回关于给定接口的实现的信息,这些内容都包装在RImplInfoPtrArray类的对象中,这可以用于向客户提供所有有效接口实现类的列表。
EXPORT_C void CCryptoInterface::ListImplementationsL(RImplInfoPtrArray& aImplInfoArray)
{
     REComSession::ListImplementationsL(KCCryptoInterfaceUid, aImplInfoArray);
}

在CCryptoInterface的虚析构函数中,它会将iDtor_ID_Key作为识别对象用的参数来调用ECOM框架。
EXPORT_C CCryptoInterface::~CCryptoInterface()
{
    // 通过ECOM,该对象已被删除
     REComSession::DestroyedImplementation(iDtor_ID_Key);
}

实现一个ECOM接口

具体类的实现必须定义在一个ECOM插件的dll中,该dll是以mmp文件中TARGETTYPE dll来构建的。在一个dll中,一个ECOM接口集合可能包含一个或多个ECOM接口的一个或多个实现。

除了接口函数,每个实现必须向ECOM"注册"一个实例化函数,即示例中的静态NewL()工厂函数。当调用REComSession::CreateImplementation()指定类直接决议或根据提示决议某个实现时,ECOM会调用类的NewL()工厂函数。

一个dll通过导出一个标准函数(ImplementationGroupProxy())向ECOM“注册”这些实例化函数。该标准函数返回一个指向TImplementationProxy对象数组的指针,而且它是一个多态dll导出的唯一函数。每个TImplementationProxy对象代表一个单独的实现类,其中还包含了可以识别实现的TUid以及一个指向其实例化方法的指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值