c#淺談反射記憶體的處理

來源:互聯網
上載者:User

標籤:c#   應用程式   開發架構   

這段時間由於公司的項目的要求,我利用c#的反射的機製做了一個用戶端架構。用戶端裡的所有的模組都是以一定形式進行提供,例如:FORM,UserControl. 在做的過程中很簡單與愉快。具體的過程如下:

1:收集客戶的需求

2:整理需求,形成必要的文檔

3:通過討論大體的得到程式的介面風格

4:由UI設計師設計出來具體的介面形式

5:通過需求封裝必要的服務(我們可以使用c#的WCF服務或者JAVA的服務)

6:製作服務管理架構

7:封裝程式要使用到的控制項

8:編寫用戶端架構

9:編寫模組

10:載入進行測試

上面說的就是簡單的一個開發的過程,當然裡麵包括了很多的汗水。一個好的程式都要滿足最基本的可卸載,可插入。即外掛程式式架構。無論是用戶端,還是服務端都要採用外掛程式式管理。

在做c#用戶端架構的時候,利用微軟的反射與原廠模式的機制的時候,裡面有個很大的問題。就是通過反射的DLL載入到記憶體中的時候無法進行記憶體的釋放,只有你關閉程式的時候才進行記憶體的釋放,這點有很大的缺陷。我在網上也找了很多的解決的辦法,但是沒有一個能夠成功的。其中最經典的是外掛程式的卸載的方式,這種方式我也進行的實驗,雖然能夠釋放部分記憶體,但是不能釋放全部的記憶體。我和很多程式員聊這個事情的時候,他們說把一切能釋放的都釋放掉。但是你就算做到這些也不能做到很好的釋放效果(也許的我的水平不行)。今天來吐槽一下VS的記憶體的釋放。VS的記憶體都是通過託管的機制進行資源的使用與釋放,對於非託管資源可以通過解構函式與其他的方式進行釋放。對於反射的情況微軟沒有給一個很好的辦法。如果程式員兄弟們有好的辦法提供給我們學習那將是個大的善果。

  我在上面說過通過卸載外掛程式的方式是可以釋放部分的記憶體,效果也還行,但是對於一些WCF服務寫的控制項,在通過遠端模式確實存在一些問題。具體的部分實現代碼如下:

 internal class AssemblyLoader : MarshalByRefObject, IDisposable
    {
        #region class-level declarations
        private Assembly a = null;
        #endregion


        #region constructors and destructors
        public AssemblyLoader(string fullPath)
        {
            if (a == null)
            {
                a = Assembly.LoadFrom(fullPath);
            }
        }


        ~AssemblyLoader()
        {
            dispose(false);
        }


        public void Dispose()
        {
            dispose(true);
        }


        private void dispose(bool disposing)
        {
            if (disposing)
            {
                a = null;
                System.GC.Collect();
                System.GC.WaitForPendingFinalizers();
                System.GC.Collect(0);
            }
        }
        #endregion
        #region public functionality
        public object GetObject(string typename, object[] ctorParms)
        {
            BindingFlags flags = BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public;


            object o = null
            ;
            if (a != null)
            {
                try
                {
                    o = a.CreateInstance(typename, true, flags, null, ctorParms, null, null);
                }
                catch
                {
                }
            }
            return o;
        }


        public object GetObject(string typename)
        {
            return GetObject(typename, null);
        }
        #endregion


 public class ObjectLoader : IDisposable
    {
        // essentially creates a parallel-hash pair setup
        // one appDomain per loader
        protected Hashtable domains = new Hashtable();
        // one loader per assembly DLL
        protected Hashtable loaders = new Hashtable();


        public ObjectLoader() 
        {}


        public object GetObject(string dllName, string typeName, object[] constructorParms)
        {
           AssemblyLoader al = null;
            object o = null;
            //Type t = null;
            try
            {
               al = (AssemblyLoader)loaders[dllName];
            }
            catch (Exception) { }


            if (al == null)
            {
                AppDomainSetup setup = new AppDomainSetup();
                setup.ShadowCopyFiles = "true";
                AppDomain domain = AppDomain.CreateDomain(dllName, null, setup);
                int key=0;
                foreach (DictionaryEntry de in domains)
                {
                    if(de.Key.ToString()==dllName)
                    {
                        key++;
                        break;
                    }
                }
                if (key == 0)
                {
                    domains.Add(dllName, domain);
                }
                object[] parms = { dllName };
                BindingFlags bindings = BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public;
                try
                {
                    //al = (BCFrameWork.Client.ClientInfrm.AssemblyLoader)domain.CreateInstanceFromAndUnwrap(
                    //  "Loader.dll", "Loader.AssemblyLoader", true, bindings, null, parms, null, null, null);
                    al = (AssemblyLoader)domain.CreateInstanceFromAndUnwrap(
                   "BestelLoadDll.dll", "BestelLoadDll.AssemblyLoader", true, bindings, null, parms, null, null, null);
                }
                catch
                {
                }
                if (al != null)
                {
                    if (!loaders.ContainsKey(dllName))
                    {
                        loaders.Add(dllName, al);
                    }
                }
            }


            if (al != null)
            {
                o = al.GetObject(typeName, constructorParms);
               
            }
            return o;
        }


        public void Unload(string dllName)
        {
            if (domains.ContainsKey(dllName))
            {
                AppDomain domain = (AppDomain)domains[dllName];
                AppDomain.Unload(domain);
                domains.Remove(dllName);
            }
        }


        ~ObjectLoader()
        {
            dispose(false);
        }


        public void Dispose()
        {
            dispose(true);
        }


        private void dispose(bool disposing)
        {
            if (disposing)
            {
                loaders.Clear();
                List<string> removeobj = new List<string>();
                foreach (object o in domains.Keys)
                {
                    string dllName = o.ToString();
                    removeobj.Add(dllName);
                }
                foreach (string item in removeobj)
                {
                    Unload(item);
                }
                domains.Clear();
                System.GC.Collect();
            }
        }
    }

調用方式很簡單,如果你瞭解反射就知道怎麼調用,這個寫法能夠滿足普通的使用者控制項的反射遠程載入,但是對於一些特殊的使用者控制項還是沒有辦法。

c#淺談反射記憶體的處理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.