跨應用程序域(AppDomain)的單例(Singleton)實現

轉載自:windows

跨應用程序域(AppDomain)的單例(Singleton)實現 - CorePlex代碼庫 - CorePlex官方網站,Visual Studio插件,代碼大全,代碼倉庫,代碼整理,分享,爲打造最有價值的在線代碼庫而不懈努力
http://www.udnz.com/code-2882.htmapp

 

工做中基於插件模式,特別是插件可能不穩定,致使主程序進程終止時,咱們每每使用應用程序域來隔離插件和主程序,但此時若是主程序中有單例(Singleton)實現,那在不一樣的AppDomain裏訪問時,會致使單例失效。爲解決這一問題,從網上找到了以下代碼。主要思想是:咱們使用一個特定名稱的應用程序域來建立和持有這些單例。每當咱們須要某個單例時,便從這個特定的應用程序域中獲取dom

注意:因爲跨AppDomain建立單例,所以單例的類的構造函數必須設置爲公共的無參構造函數,這一點應當留意。ide

see:http://www.dolittle.com/blogs/einar/archive/2007/05/18/cross-appdomain-singleton.aspx函數

 

代碼正文

/* *************************
 * Cross AppDomain Singleton
 * *************************
 *
 * The solution we want is that the singleton class is created in a
 * given AppDomain and in all other AppDomains we get a transparent
 * proxy to that singleton.
 *
 * In order to do this we need to have the ability to enumerate
 * through existing AppDomains in order to create an instance in the
 * correct AppDomain (at least I found this to be cool way of doing it).
 * I came across a thread on microsoft.public.dotnet.framework.clr
 * that gave me a good solution (http://groups.google.com/group/microsoft.public.dotnet.framework.clr/browse_frm/thread/dba9c445ad8d5c3/9df14bf0af393c28?lnk=st&q=enumerate+appdomain+group%3Amicrosoft.public.dot%20net.*&rnum=5#9df14bf0af393c28)
 *
 * You need to add a reference to the MSCOREE.TLB which is situated
 * in the .net directory (c:\windows\microsoft.net\framework\v2.0.50727,
 * depends on your runtime version). When you add a reference to it
 * you'll get an Interop.mscoree.dll added to your output directory.
 * You will have to have this alongside your deployment if you're going
 * to use this in a solution.
 */
/// <summary>
/// Cross AppDomain Singleton
/// </summary>
/// <typeparam name="T"></typeparam>
public class SingletonDomain<T> : MarshalByRefObject where T : new()
{
    private static readonly string AppDomainName = "SingletonAppDomain";
    private static T _instance;
 
    private static AppDomain GetAppDomain(string friendlyName)
    {
        IntPtr enumHandle = IntPtr.Zero;
        mscoree.CorRuntimeHost host = new mscoree.CorRuntimeHost();
        try
        {
            host.EnumDomains(out enumHandle);
            object domain = null;
            while (true)
            {
                host.NextDomain(enumHandle, out domain);
                if (domain == null)
                {
                    break;
                }
                AppDomain appDomain = (AppDomain)domain;
                if (appDomain.FriendlyName.Equals(friendlyName))
                {
                    return appDomain;
                }
            }
        }
        finally
        {
            host.CloseEnum(enumHandle);
            Marshal.ReleaseComObject(host);
            host = null;
        }
        return null;
    }
 
    public static T Instance
    {
        get
        {
            if (null == _instance)
            {
                AppDomain appDomain = GetAppDomain(AppDomainName);
                if (null == appDomain)
                {
                    AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
                    setup.ApplicationName = "SingletonAppDomain";
 
                    // Set up the Evidence
                    Evidence evidence = new Evidence(AppDomain.CurrentDomain.Evidence);
 
                    appDomain = AppDomain.CreateDomain(AppDomainName, evidence, setup);
                }
                Type type = typeof(T);
                T instance = (T)appDomain.GetData(type.FullName);
                if (null == instance)
                {
                    instance = (T)appDomain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
                    appDomain.SetData(type.FullName, instance);
                }
                _instance = instance;
            }
            return _instance;
        }
    }
}
相關文章
相關標籤/搜索