• ArcEngine-小改进源码的ComReleaser类


    ArcEngine-小改进源码的ComReleaser类

    虽然ArcEngine有自己的ComReleaser,放在ESRI.ArcGIS.ADF.Connection.Local.dll中,但是经常在项目中引用不到,或者在低版本的AO中不存在,所以自己看了源码,然后加上自己的一些理解做了改进,放到项目中直接用。

    ComReleaser代码

    using System;
    using System.Collections;
    using System.Runtime.InteropServices;
    /// <summary>
    /// Com对象释放器
    /// </summary>
    [Serializable]
    public class ComReleaser : IDisposable
    {
        private ArrayList m_array;
        /// <summary>
        /// Default Constructor
        /// </summary>
        public ComReleaser()
        {
            m_array = ArrayList.Synchronized(new ArrayList());
        }
    
        /// <summary>
        /// Destructor
        /// </summary>
        ~ComReleaser()
        {
            Dispose(disposing: false);
        }
    
        /// <summary>
        /// Manages the lifetime of any COM object.  The method will deterministically release the object during the dispose process.
        /// </summary>
        /// <remarks>
        /// Marshal.ReleaseComObject will be called during the disposal process on this Interface pointer until its RCW
        /// reference count becomes 0.  
        /// NOTE: Do not add ServerObject interfaces like IMapServer, IGeocodeServer, IMapServerLayout or IMapServerObjects.
        /// </remarks>
        /// <param name="o">The COM object to manage.</param>
        public void ManageLifetime(object o)
        {
            m_array.Add(o);
        }
    
        /// <summary>
        /// Implementation of IDisposable method Dispose()
        /// The Dispose method should release all the resources that it owns for unmanaged code resources.
        /// </summary>
        public void Dispose()
        {
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }
    
        /// <summary>
        /// Dispose method implementation from IDisposable Interface
        /// </summary>
        /// <param name="disposing">
        /// Boolean value indicating to the method whether
        /// or not it should also dispose managed objects
        /// </param>
        protected virtual void Dispose(bool disposing)
        {
            int count = m_array.Count;
            //从后往前释放,因为添加的顺序总是从大到小,先释放小对象
            for (int i = count - 1; i >= 0; i--)
            {
                object comObj = m_array[i];
                m_array.RemoveAt(i);
                if (comObj != null && Marshal.IsComObject(comObj))
                {
                    while (Marshal.ReleaseComObject(comObj) > 0)
                    {
                    }
                }
            }
            if (disposing)
            {
                m_array = null;
            }
        }
    
        /// <summary>
        /// Decrements the reference count to zero of the supplied runtime callable wrapper.
        /// </summary>
        /// <param name="o">The COM object to release.</param>
        public static void ReleaseCOMObject(object o)
        {
            if (o != null && Marshal.IsComObject(o))
            {
                while (Marshal.ReleaseComObject(o) > 0)
                {
                }
            }
        }
    }
    

    整个ComReleaser实现了IDisposable接口,可以在Using域中把创建的COM对象通过ManageLifetime方法加到内部的ArrayList中,然后在Using作用域结束的时候,从后往前遍历释放添加的COM对象。
    这个类的好处在于在面对业务中大量创建使用的COM对象,比如IWorkspace、IFeatureClass、ICursor等时,不用使用try...finally写很丑的释放代码。而且按照一般的业务代码逻辑,通常都是从大到小的创建对象IWorkspace->->IFeatureDataset->IFeatureClass->ICursor等,那么依次添加到内部ArrayList后,再反向释放,能减少几次引用计数,释放速度更快,释放对象更干净。

    使用实例

    using (ComReleaser comReleaser = new ComReleaser())
    {
        IWorkspace workspace = AEComFunc.OpenFeatureWorkspace(dbPath);
        comReleaser.ManageLifetime(workspace);
        string xzydyh = "XZYDYH";
        IFeatureClass xzydyh_fc = (workspace as IFeatureWorkspace).OpenFeatureClass(xzydyh);
        comReleaser.ManageLifetime(xzydyh_fc);
        ICursor cursor = xzydyh_fc.Search(null, true) as ICursor;
        comReleaser.ManageLifetime(cursor);
        ESRI.ArcGIS.Geodatabase.IRow row;
        while ((row = cursor.NextRow()) != null)
        {
            //处理逻辑
        }
    }
    
  • 相关阅读:
    Java学习之路(四)
    HTML学习之canves元素
    一些常用的SQL查询语句
    数据库实现动态表头
    Java学习之路(三)
    Java学习之路(二)
    Java学习之路(一)
    UML类图几种关系的总结(转)
    vue 项目全局修改element-ui的样式
    NGINX 资料
  • 原文地址:https://www.cnblogs.com/chenyifaer-67373/p/15507261.html
Copyright © 2020-2023  润新知