起因
事情的起因是這樣的
基於某些無法避免的因素
我有2個dll 暫且叫 a.dll 和 b.dll
這2個類庫中有一部分完全相同的代碼(下文中稱為代碼C)——遍歷當前應用程序下的所有類庫文件,並注入插件(沒錯,就是IOC了)
當開發人員僅引用a.dll或僅b.dll的時候,並沒有任何問題
但是如果一個項目需要同時引用 a.dll 和 b.dll 那么麻煩就來了
那部分完全相同的代碼會被執行2次, 所有插件都會被加載2次
經過
最簡單的方案當然是把a.dll和b.dll中相同的代碼 抽出成c.dll
然后之前引用a.dll的 需要同時引用a.dll和c.dll
雖然可以很簡單的解決問題,但是同樣他的修改成本和用戶體驗是最差的(軟件設計也要用戶體驗),
這個方案被保留為無論如何都無法解決問題才會使用的方案
由於a.dll和b.dll互相不知道對方的存在,所以無法直接通知對方我已經執行過代碼C了
想過中Mutex,也想過用反射,都因為有各種副作用而放棄了
其他更多中間嘗試各種方案的過程就不說了...
結果
最后靈光一閃,猛然想到了字符串駐留池(不了解的自己百度,或者搜博客園相關文章)
string.Intern 將字符串放入駐留池
string.IsInterned 返回字符串在駐留池中的引用,如果返回null則說明該字符串沒有在駐留池中
突然就有了主意了:約定一個字符串,當任何一個代碼C被執行的時候,先判斷這個字符串是否在駐留池中,如果不在則執行代碼,執行完成后將這個字符串放入駐留池
當然這里有一個需要注意的地方,字符串如果直接固定寫帶代碼中,在編譯期間就會被放入駐留池
栗子中,xxx是硬編碼在代碼中的 可以看出xxx在駐留池中,而NewGuid的字符串 沒有在駐留池中
所有硬編碼的string都會被編譯成常量,常量字符串也是在駐留池中的
加上字符串是引用類型,但是有常量的概念這個特性,所以全局鎖也搞定了,直接鎖定一個常量字符串就行了
所以 實際項目中的代碼如下: