65.9K
CodeProject 正在变化。 阅读更多。
Home

ATL PersistXML 实现

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2002年10月28日

2分钟阅读

viewsIcon

130488

downloadIcon

1296

最简单的方法是将 XML 持久性添加到现有的基于 IDispatch 的 ATL COM 对象。

Sample Image - atlpersistxmlapp.gif

引言

想想,有多少次你想向现有的 ATL COM 对象添加 PersistXML 支持? 确实,这应该像添加 IpersistPropertyBagImplIpersistStreamInitImpl ATL 模板一样简单。 此外,这些类已经共享了属性映射的使用。

BEGIN_PROP_MAP( CMyClass )
    PROP_ENTRY_EX( "Caption", DISPID_CAPTION, 
CLSID_MyClassPropPage2, IID_IMyDual1 ) END_PROP_MAP( )

让我们这样做来添加 XML 支持!

接口

我使用了 IPersistVarXML 接口名称,因为 Microsoft 已经为 Commerce Server 2002 采用了 IPersistXML,并且它不如我想要的那么方便。(它使用 BSTR 作为 XML 输入输出,而不是 VARIANT)。

我设计了自己的 IPersistVarXML 接口(请参阅下面的 IDL 描述)。此接口支持 VARIANT 作为 XML 输入和输出。 实际上,它甚至可以使用 ISAXContentHandlerfor (MXXMLWriter) 进行 XML 输出!

[
object,
    uuid(B66873EC-BBFF-11D4-A802-112233445566),
    helpstring("IPersistVarXML Interface"),
    pointer_default(unique)
]
interface IPersistVarXML : IUnknown
{
    [propget, helpstring("property ElementName")] 
       HRESULT ElementName([out, retval] BSTR* bstrElementName);
    HRESULT LoadXML([in] VARIANT varSource, [in, optional, 
            defaultvalue(0L)] IUnknown * pAttributes);
    HRESULT SaveXML([in] VARIANT varSource);
};
template <class T> 
class ATL_NO_VTABLE IPersistVarXMLImpl : 
                            public IPersistVarXML, 
                            public ISAXContentHandlerImpl<T>

此实现大量使用 Microsoft MS XML SDK(版本 3 及更高版本)。 因此,您需要在您的机器上安装msxml3.dll或更高版本。(此 DLL 始终与所有最新版本的 MS Internet Explorer 一起提供,或者可以从 www.microsoft.com/xml 单独安装)。

支持的属性

如果您的类已经从 IPerPropertyBrowsingImplIPersistPropertyBagImplIPersistStreamInitImplISpecifyPropertyPagesImpl 类之一派生,并且具有 BEGIN_PROP_MAP() 宏,则 IPersistVarXMLImpl 可以重用它,您无需执行任何额外的操作!

如果您需要保存内部对象或手动处理某些 XML 条目,则可以使用 BEGIN_XML_CONTENT_MAP () 宏。 它为 XML 解析器和保存器创建一个额外的 MAP。 此映射是可选的。

BEGIN_XML_CONTENT_MAP(CMyClass)
    XML_CONTENT_LOAD_HANDLER(“ENTRY”, OnENTRY_HandleFunction)
    XML_CONTENT_ENTRY(&m_objInternal1)
    XML_CONTENT_SAVE_ENTRY(&m_objInternal2)
    XML_CONTENT_CREATE_OBJECT( "ObjectName", 
         CLSID_AnObject, OnXMLContextCreateAnObjec)
END_XML_CONTENT_MAP()

HRESULT OnENTRY_HandleFunction(ISAXAttributes * pAttributes);
HRESULT OnXMLContextUser(IPersistVarXML* pAnOblect);

CComObjectGlobal<CMyInternalObject>    m_objInternal1;
CComObjectGlobal<CMyInternalObject>    m_objInternal2;

如何添加 XML 支持

要向您的 ATL COM 对象添加 PersistXML 支持,您需要

  • 在您的项目中添加 include:IPersistVarXMLImpl.hIPersistVarXMLImpl.cpp
    #include IPersistVarXMLImpl.h
  • IPersistVarXMLImpl 派生您的类
    //////////////////////////////////////////////////////
    // CSystemUser
    class ATL_NO_VTABLE CSystemUser : 
        public CComObjectRootEx<CComSingleThreadModel>,
        public CComCoClass<CSystemUser, &CLSID_SystemUser>,
        public IDispatchImpl,
        public IPersistVarXMLImpl<CSystemUser>
    {
    
  • 修改 COM 映射。 将 ISAXContentHandlerIPersistVarXML 接口添加到您的对象。
    BEGIN_COM_MAP(CSystemUser)
        COM_INTERFACE_ENTRY(ISystemUser)
        COM_INTERFACE_ENTRY(IDispatch)
        COM_INTERFACE_ENTRY(ISAXContentHandler)
        COM_INTERFACE_ENTRY(IPersistVarXML)
    END_COM_MAP()
  • 添加公共成员
    unsigned m_bRequiresSave:1;
  • 添加和/或修改属性映射。 只添加需要 XML 持久化的属性!
    BEGIN_PROP_MAP(CSystemUser)
        PROP_ENTRY_EX( "Name",    1,    CLSID_NULL,    IID_ISystemUser )
        PROP_ENTRY_EX( "Address", 2,    CLSID_NULL,    IID_ISystemUser )
    END_PROP_MAP()
  • 为额外功能添加 XML 上下文映射(处理动态对象创建和保存,不支持标准数据类型等)。
    BEGIN_XML_CONTENT_MAP(T)
        XML_CONTENT_SAVE_ENTRY(&m_objInternal)
        XML_CONTENT_LOAD_HANDLER("ALIAS",OnXMLContextAlias)
    END_XML_CONTENT_MAP()

就是这样!

用途

使用 IPersistVarXMLLoadXML(varSource)SaveXML(varDest) 函数来保存和加载 XML 内容。 VarSource 可以是所有支持的 ISAXXMLReader::parse() Variant 类型

“The application can use this method to instruct the reader to begin 
parsing a document from a variety of sources. Supported VARIANT types are: 
VT_BSTR, SafeArray of bytes (VT_ARRAYVT_UI1), VT_UNK(IStream), 
and VT_UNK(ISequentialStream). One-level referencing is also permitted.
VT_BYREF | VT_VARIANT d
VT_BYREF | VT_VARIANT -> VT_BSTR
VT_BYREF | VT_VARIANT -> IStream
VT_BYREF | VT_VARIANT -> VT_ARRAY|VT_UI1.”
(MS XML SDK manual)

varDest 可以是所有支持的 IMXWriter::output() Variant 类型

“Determines the output for MXXMLWriter. By default, the output property 
is a BSTR (string) value. You can also set this property to any 
implementation of the IStream interface, and the resulting document 
will be written into the provided IStream. Setting this property to the 
empty value (VT_EMPTY or " ") will return 
output to the internal string and reset it.”
(MS XML SDK manual)

因为此实现使用 CComDispatchDriver::PutProperty()CComDispatchDriver::GetProperty(),所以基类必须是 IDispatch 派生的。

示例应用程序

我已经创建了两个 Visual Studio 6.0 项目,作为如何轻松地向 ATL 对象添加 XML 支持的示例

  • AtlPersistXmlSample.exe – 基于主对话框的应用程序,以及
  • MyObjects.dllSystemUser 和类实现。

它可以为 Unicode 和 ASCII 平台编译。 将 AtlPersistXmlSample.dsw 工作区加载到 Visual Studio 中,构建两个项目并运行。 它演示了整个应用程序的 XML 文件保存/恢复配置,以及动态 XML 字符串生成(包括所有内部类和集合)和可视化。

参考资料

© . All rights reserved.