COM持久存储

 
       组件实现了IPersistStream、IPersistStorage、IPersistPropertyBag接口。这些接口都提供了Load和Save方法。这些接口统称为IPersistMedium。
       当需要保存组件的属性时------
1) 客户查询组件的IPersistMedium接口;
2) 调用IPersistMedium::GetClassID方法,然后将CLSID保存到永久介质上;
3) 调用IPersistMedium::Save方法将对象属性保存到永久介质中。
当需要恢复组建对象时------
1) 客户从介质中读取CLSID,创建组件对象
2) 查询组件实现的接口IPersistMedium
3) 调用IPersistMedium::Load方法装载对象状态
 
IPersistMedium均派生自IPersist接口,由组件实现。但是他们保存/恢复数据的方式依赖于客户传递进来的IMedia接口。IMedia接口包括:IStream、IStorage、IPropertyBag接口。也就是说,使客户决定了何时、以什么方式保存或者恢复组件对象状态,而组件对象只提供或者接受状态数据。
IStream接口应用
       IStream接口将数据抽象为二进制的字节流。我们可以在自己的对象中实现IStream接口,COM提供了两种形式的IStram接口的实现,一种是以内存形式,一种是通过复合文件。下面分别举例:
使用内存中预定义的IStream接口形式----
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
     ::CoInitialize(NULL);
     CComPtr<IStream> pStream;
     HRESULT hr=CreateStreamOnHGlobal(NULL,TRUE,&pStream);
     BYTE Buffer[1024];
     memset(Buffer,1,1024);
     ULONG Size=0;
 
     hr=pStream->Write(Buffer,1024,&Size);
    
     BYTE Buffer2[1024];
     memset(Buffer2,0,1024);
     ULONG Size2=0;
     LARGE_INTEGER x;
     x.LowPart=-1024;
     x.HighPart=0;
     hr=pStream->Seek(x,STREAM_SEEK_CUR ,0);// 从当前位置回退1024个字节
     hr=pStream->Read(Buffer2,1024,&Size2);
 
     pStream.Release();
     ::CoUninitialize();
     return 0;
}
 
       。。。
       IPersistStramInit是对IPersistStream接口的增强,但是两者不能在同一个组件中实现。组件要实现自己的IPersistStreamInit接口。客户要提供IStream接口的有效指针,IPersistStramInit接口的Load和Write方法是通过客户提供的ISream接口完成工作的。
       下面的例子中,我们将实现进程内组件B,然后实现进城外组件A,B实现了IPersistStreamInit接口。A创建了IStram接口(通过复合文件的方式)。A通过调用B实现的IPersistStreamInit接口的方法实现B对象的属性永久保存和属性恢复。
       下面是组件CB类的源代码,后面有注释符的就是我们手工添加的代码:
 
// B.h : CB 的声明
 
#pragma once
#include "resource.h"       // 主符号
#include "StreamObject.h"
// CB
class ATL_NO_VTABLE CB :
     public CComObjectRootEx<CComSingleThreadModel>,
     public CComCoClass<CB, &CLSID_B>,
     public IPersistStreamInit,/
     public IDispatchImpl<IB, &IID_IB, &LIBID_StreamObjectLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public :
     CB()
     {
         m_Dirty=true;
     }
 
DECLARE_REGISTRY_RESOURCEID(IDR_B)
 
 
BEGIN_COM_MAP(CB)
     COM_INTERFACE_ENTRY(IB)
     COM_INTERFACE_ENTRY(IDispatch)
     COM_INTERFACE_ENTRY(IPersistStreamInit)//
     COM_INTERFACE_ENTRY2(IPersist,IPersistStreamInit)///
END_COM_MAP()
 
     DECLARE_PROTECT_FINAL_CONSTRUCT()
 
     HRESULT FinalConstruct()
     {
         return S_OK;
     }
    
     void FinalRelease()
     {
        
     }
 
public :
 
     STDMETHODIMP GetClassID(CLSID* pClassID)///
     {
         return S_OK;
     }
     STDMETHODIMP IsDirty()
     {
         return m_Dirty ? S_OK:S_FALSE;
     }
 
     STDMETHODIMP InitNew()///
     {
         m_Value=L"default";
         return S_OK;
     }
 
     STDMETHODIMP Load(IStream* pStream)///
     {
         return m_Value.ReadFromStream(pStream);
     }
 
     STDMETHODIMP Save(IStream* pStream,BOOL fClearDirty)///
     {
         if(fClearDirty)
         {
              m_Dirty=false;
         }
         return m_Value.WriteToStream(pStream);
     }
 
     STDMETHODIMP GetSizeMax(ULARGE_INTEGER* pCBSize)
     {
         if(pCBSize==NULL)
              return E_POINTER;
         pCBSize->QuadPart=sizeof(ULONG);
         pCBSize->QuadPart+=SysStringByteLen(m_Value);
         return S_OK;
     }
 
private :
     CComBSTR m_Value;
     bool m_Dirty;
 
};
 
OBJECT_ENTRY_AUTO(__uuidof(B), CB)
 
       现在我们来开发客户程序,客户程序要创建流对象,并把流接口指针传递给
组件。
 
// StreamClient.cpp : 定义控制台应用程序的入口点。
//
 
#include "stdafx.h"
#import "StreamObject.tlb" no_namespace raw_interfaces_only named_guids
 
int _tmain(int argc, _TCHAR* argv[])
{
     ::CoInitialize(NULL);
     CComPtr<IB> spB;
     HRESULT hr=spB.CoCreateInstance(CLSID_B);
     CComPtr<IPersistStreamInit> spPersistStreamInit;
     hr=spB->QueryInterface(&spPersistStreamInit);
     hr=spPersistStreamInit->InitNew();
    
     CComPtr<IStream> pStream;
     hr=CreateStreamOnHGlobal(NULL,TRUE,&pStream);
     hr=spPersistStreamInit->Save(pStream,TRUE);
 
     LARGE_INTEGER x;
     x.QuadPart=0;
     hr=pStream->Seek(x,STREAM_SEEK_SET,0);
     CComBSTR str;
     hr=str.ReadFromStream(pStream);
 
     pStream.Release();
     spPersistStreamInit.Release();
     spB.Release();
    
     ::CoUninitialize();
     return 0;
}
 
ATL对实现IPersistStreamInit接口的支持
       刚才我们的组件B实现IPersistStreamInit接口的时候,采用了传统的com继承方式,繁琐而且容易出错。ATL提供了IPersistStreamInitImpl类来供我们简化实现过程。
 
原文链接: http://blog.csdn.net/sheismylife/article/details/1154704

转载于:https://my.oschina.net/chen106106/blog/45615

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值