ArcObjects编程方法(五):对象复制的实现

版本:ArcGIS 10 

参考:http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#/Implementing_cloning/0001000002tw000000/

ArcGIS支持IClone接口的对象,可以通过Clone()方法复制对象,其过程比创建新变量要复杂。一下展现创建两个指向同一个对象的变量:

[C#]

IPoint pointOne = new PointClass();
IPoint pointTwo = pointOne;

001

以下展现通过IClone接口复制对象:

[C#]

IClone clone = pointOne as IClone;
pointTwo = clone.Clone()as IPoint;

002

深复制(deep clone)和浅复制(shallow clone)

如果被复制的对象只包含值类型的数据,则复制过程比较简单,复制体将包含所有被复制对象的信息。但是,当被复制对象包含引用类型的数据时,复制分为深度复制和初级复制。深复制将创建复制对象及其引用指向的对象,浅复制只会复制其引用。过程如下图:

003

深复制例子:当图形单元被复制,其几何属性和样式属性也将被复制,复制体完全独立于以前的对象。

浅复制例子:在一个要素类,一个几何要素被复制,其空间引用属性指向同一对象,用来定义同一坐标系。

因此在复制对象时,要根据具体需要选择复制的方式,特别是对象包含引用数据的时候。

 

复制的实现

一般有两种方式实现复制。一种是被复制对象创建实例,并将所有成员信息复制到新建的实例。另一种方式是根据对象持续保存的特性,先将对象临时保存在内存流中,再从内存流中读取对象,这要求对象实现IPersist接口和IPersistStream接口。

对象实现Clone方法:

[C#]

public IClone Clone()
{
    ClonableObjClass obj = new ClonableObjClass();
    obj.Assign(this);

    return (IClone)obj;
}

Assign方法:

public void Assign(IClone src)
{
    //1. 确认引用非空
    if (null == src)
    {
        throw new COMException("Invalid object.");
    }

    //2. 类型符合要求
    if (!(src is ClonableObjClass))
    {
        throw new COMException("Bad object type.");
    }

    //3. 将src的属性复制给现在的实例
    ClonableObjClass srcClonable = (ClonableObjClass)src;
    m_name = srcClonable.Name;
    m_version = srcClonable.Version;
    m_ID = srcClonable.ID;

    //浅复制 
    m_spatialRef = srcClonable.SpatialReference;
}

上述的Assign只是把值赋给新的实例实现浅复制,也可以通过如下代码实现深复制:

[C#]

public void Assign(IClone src)
{
    //1. 确认引用非空
    if (null == src)
    {
        throw new COMException("Invalid object.");
    }

    //2. 类型符合要求
    if (!(src is ClonableObjClass))
    {
        throw new COMException("Bad object type.");
    }

    //3. 将src的属性复制给现在的实例
    ClonableObjClass srcClonable = (ClonableObjClass)src;
    m_name = srcClonable.Name;
    m_version = srcClonable.Version;
    m_ID = srcClonable.ID;

    //深复制
    IClone cloned = srcClonable.SpatialReference as IClone;
    if (null != cloned)
    {
       m_spatialRef = (ISpatialReference)cloned.Clone();
    }
}

通过ObjectCopy进行深复制:

[C#]

//通过ObjectCopy深复制SpatialReference
if (null == srcClonable.SpatialReference)
    m_spatialRef = null;
else
{
    IObjectCopy objectCopy = new ObjectCopyClass();
    object obj = objectCopy.Copy((object)srcClonable.SpatialReference);
    m_spatialRef = (ISpatialReference)obj;
}

IsEqual方法判断被复制的实例和新实例的成员信息是否相同:

[C#]

public bool IsEqual(IClone other)
{
    //1. 非空
    if (null == other)
        throw new COMException("Invalid object.");

    //2. 类型合法
    if (!(other is ClonableObjClass))
        throw new COMException("Bad object type.");

    ClonableObjClass otherClonable = (ClonableObjClass)other;

    //测试属性是否相等
    if (otherClonable.Version == m_version && otherClonable.Name == m_name &&
        otherClonable.ID == m_ID && ((IClone)otherClonable.SpatialReference).IsEqual
        ((IClone)m_spatialRef))
    )return true; 

    return false; 
}

IsIdentical方法判断两者是否指向内存中的同一对象:[C#]

public bool IsIdentical(IClone other)
{
    //1.非空
    if (null == other)
        throw new COMException("Invalid object.");

    //2. 类型合法
    if (!(other is ClonableObjClass))
        throw new COMException("Bad object type.");

    //3. 判断
    if ((ClonableObjClass)other == this)
        return true;

    return false;
}
 
posted @ 2011-09-24 17:02  xmwang  阅读(876)  评论(0编辑  收藏  举报