• 跨应用程序域(AppDomain)的单例(Singleton)实现


    转载自:

    跨应用程序域(AppDomain)的单例(Singleton)实现 - CorePlex代码库 - CorePlex官方网站,Visual Studio插件,代码大全,代码仓库,代码整理,分享,为打造最有价值的在线代码库而不懈努力
    http://www.udnz.com/code-2882.htm

    工作中基于插件模式,特别是插件可能不稳定,导致主程序进程终止时,我们往往使用应用程序域来隔离插件和主程序,但此时如果主程序中有单例(Singleton)实现,那在不同的AppDomain里访问时,会导致单例失效。为解决这一问题,从网上找到了如下代码。主要思想是:我们使用一个特定名称的应用程序域来创建和持有这些单例。每当我们需要某个单例时,便从这个特定的应用程序域中获取

    注意:由于跨AppDomain创建单例,因此单例的类的构造函数必须设置为公共的无参构造函数,这一点应当留意。

    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:windowsmicrosoft.netframeworkv2.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;
            }
        }
    }
    

      

  • 相关阅读:
    elastic
    Leetcode题库 第十行
    Leetcode题库-实现strStr()
    Redis持久化
    Redis的数据结构及应用场景
    Redis缓存的淘汰策略
    Redis缓存常见问题
    Redis面试题1
    消息队列的原理及选型
    【转载】java高并发/mysql/mybatis/spring博客
  • 原文地址:https://www.cnblogs.com/happycat1988/p/3219939.html
Copyright © 2020-2023  润新知