2009년 12월 27일 일요일

[ArcObjects]IPersistStream

IPersistStream, IMemoryBlobStream 인터페이스를 이용하여 Map의 Layer를 Table의 Blob Field에 저장하고 불러오는 예제입니다.

아래 예제는 다음을 가정합니다.
 - 테이블이 생성되어 있으며, 테이블에는 LYR_BLOB(esriFieldTypeBlob) 필드가 있음
 - 확장을 위해 IPropertySet 인터페이스에 IPersistStream(ILayer)를 저장해서 활용함


▣ ILayer 외 저장가능한 ArcObjects 인터페이스들은 IMap, IGeometry, IElement, ISymbol 등 IPersistStream 인터페이스를 구현한 클래스들입니다.
 - http://resources.esri.com/help/9.3/ArcGISEngine/ArcObjects/esrisystem/IPersistStream.htm

① Blob 필드에 저장하는 Method

[code c#]
public uint SaveStream(ESRI.ArcGIS.Geodatabase.IRow ipRow, string fieldName, ILayer streamValue)
{
    int idxField = ipRow.Fields.FindField(fieldName);
    if (idxField == -1) return 0;

    ESRI.ArcGIS.esriSystem.IMemoryBlobStream ipMemBlobStream = null;
    ipMemBlobStream = new ESRI.ArcGIS.esriSystem.MemoryBlobStreamClass();

    ESRI.ArcGIS.esriSystem.IObjectStream ipObjectStream = null;
    ipObjectStream = new ESRI.ArcGIS.esriSystem.ObjectStreamClass();

    ipObjectStream.Stream = ipMemBlobStream;

    ESRI.ArcGIS.esriSystem.IPropertySet ipPropertySet = null;
    ipPropertySet = new ESRI.ArcGIS.esriSystem.PropertySetClass();
    ipPropertySet.SetProperty("Layer", streamValue);

    ESRI.ArcGIS.esriSystem.IPersistStream ipPersistStream = (ESRI.ArcGIS.esriSystem.IPersistStream)ipPropertySet;
    ipPersistStream.Save(ipObjectStream, 0);

    ipRow.set_Value(idxField, ipMemBlobStream);

    return ipMemBlobStream.Size;
}
[/code]
② Map의 Layer를 저장하는 샘플 코드

[code c#]
private void SaveMapLayerToBlob(IMap ipMap, ITable ipTable)
{
    if (ipMap.LayerCount == 0) return;

    IWorkspace ipWs = ((IDataset)ipTable).Workspace;
    IWorkspaceEdit ipWsEdit = (IWorkspaceEdit)ipWs;
    ipWsEdit.StartEditing(false);

    for (int k = 0; k < ipMap.LayerCount; k++)
    {
        ILayer ipLayer = ipMap.get_Layer(0);

        IRow ipRow = ipTable.CreateRow();
        uint streamSize = SaveStream(ipRow, "LYR_BLOB", ipLayer);

        ipRow.Store();
    }

    ipWsEdit.StopEditing(true);
}
[/code]
③ Blob 필드에서 Layer를 불러오는 Method

[code c#]
public ILayer LoadStream(ESRI.ArcGIS.Geodatabase.IRow ipRow, string fieldName)
{
    int idxField = ipRow.Fields.FindField(fieldName);
    if (idxField == -1) return null;

    ESRI.ArcGIS.esriSystem.IMemoryBlobStream ipMemBlobStream = null;
    ipMemBlobStream = (ESRI.ArcGIS.esriSystem.IMemoryBlobStream)ipRow.get_Value(idxField);

    ESRI.ArcGIS.esriSystem.IObjectStream ipObjectStream = null;
    ipObjectStream = new ESRI.ArcGIS.esriSystem.ObjectStreamClass();

    ipObjectStream.Stream = ipMemBlobStream;

    ESRI.ArcGIS.esriSystem.IPropertySet ipPropertySet = null;
    ipPropertySet = new ESRI.ArcGIS.esriSystem.PropertySetClass();

    ESRI.ArcGIS.esriSystem.IPersistStream ipPersistStream = null;
    ipPersistStream = (ESRI.ArcGIS.esriSystem.IPersistStream)ipPropertySet;

    ILayer ipLayer = null;
    try
    {
        ipPersistStream.Load(ipObjectStream);

        ipLayer = (ILayer)ipPropertySet.GetProperty("Layer");
    }
    catch (Exception Ex)
    {
        System.Diagnostics.Debug.WriteLine(Ex.Message);
    }

    return ipLayer;
}
[/code]
④ Table에 저장된 Layer를 지도에 추가하는 샘플 코드

[code c#]
private void LoadLayers(IMap ipMap, ITable ipTable, IQueryFilter ipQueryFilter)
{
    ipMap.ClearLayers();

    ICursor ipCursor = ipTable.Search(ipQueryFilter, false);
    IRow ipRow = ipCursor.NextRow();

    while (ipRow != null)
    {
        ILayer ipLayer = LoadStream(ipRow, "LYR_BLOB");

        if (ipLayer != null)
        {
            ipMap.AddLayer(ipLayer);
        }

        ipRow = ipCursor.NextRow();
    }
    System.Runtime.InteropServices.Marshal.ReleaseComObject(ipCursor);
}
[/code]