• AppDomain


    AppDomain与mscoree

    using mscoree;
    
    private void DeleteAppDomain(string friendName)
    {
        UnloadAppDomain(friendName);
    }
    
    public static void UnloadAppDomain(string friendName)
    {
        var domain = GetAppDomain(friendName);
        AppDomain.Unload(domain);
    }
    public static AppDomain GetAppDomain(string friendName)
    {
        var domains = GetAppDomains();
        return domains.FirstOrDefault(s => s.FriendlyName == friendName);
    }
    
    public static AppDomain GetMainAppDomain()
    {
        IntPtr ptr = IntPtr.Zero;
        var host = new CorRuntimeHost();
        try
        {
            host.EnumDomains(out ptr);
            object domain = null;
            while (true)
            {
                host.NextDomain(ptr, out domain);
                if (domain == null)
                {
                    return null;
                }
                if (!System.Runtime.Remoting.RemotingServices.IsTransparentProxy(domain))
                {
                    break;
                }
            }
            return (AppDomain)domain;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            return null;
        }
        finally
        {
            host.CloseEnum(ptr);
            Marshal.ReleaseComObject(host);
        }
    }
    public static IList<AppDomain> GetAppDomains()
    {
        IList<AppDomain> rslt = new List<AppDomain>();
        IntPtr ptr = IntPtr.Zero;
        var host = new CorRuntimeHost();
        try
        {
            host.EnumDomains(out ptr);
            object domain = null;
            while (true)
            {
                host.NextDomain(ptr, out domain);
                if (domain == null)
                {
                    break;
                }
                rslt.Add((AppDomain)domain);
            }
            return rslt;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            return new List<AppDomain>();
        }
        finally
        {
            host.CloseEnum(ptr);
            Marshal.ReleaseComObject(host);
        }
    }
    

    跨域加载

    /// <summary>
    /// 跨域加载
    /// </summary>
    /// <param name="friendlyName"></param>
    /// <param name="assemblyName"></param>
    /// <returns></returns>
    public static ProxyDomainObject CrossDomainLoad(string friendlyName, string assemblyName)
    {
        ProxyDomainObject proxy = null;
        try
        {
            AppDomain domain = ProxyDomainObject.GetSiblingDomain(friendlyName);
            if (domain == null)
            {
                Console.WriteLine(".................当前域不存在,创建新应用程序域,并加载dll");
                domain = ProxyDomainObject.BuildSiblingDomain(AppDomain.CurrentDomain, friendlyName);
                domain.AssemblyLoad += ChildDomain_AssemblyLoad;
                proxy = (ProxyDomainObject)domain.CreateInstanceFromAndUnwrap(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + AppDomain.CurrentDomain.SetupInformation.ApplicationName, typeof(ProxyDomainObject).FullName);
    
                proxy.SetDomainDelegate(domain, AppDomain.CurrentDomain);
                proxy.LoadAssembly(assemblyName);
            }
            else
            {
                Console.WriteLine(".................当前域存在,直接加载dll");
                proxy = (ProxyDomainObject)domain.CreateInstanceFromAndUnwrap(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + AppDomain.CurrentDomain.SetupInformation.ApplicationName, typeof(ProxyDomainObject).FullName);
                proxy.LoadAssembly(assemblyName);
            }
            Console.WriteLine(".................childDomain: " + domain.Id + "_" + domain.SetupInformation.ApplicationName + "_" + domain.FriendlyName);
        }
        catch (Exception ex)
        {
            Console.WriteLine(".................CrossDomainLoad: " + ex.Message);
        }
        return proxy;
    }
    
    private static void ChildDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
    {
        Console.WriteLine("==========================" + args.LoadedAssembly.Location + ":  " + args.LoadedAssembly.FullName);
    }
    

    ProxyDomainObject

    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Security.Policy;
    using System.Threading.Tasks;
    using System.Windows;
    public class ProxyDomainObject : MarshalByRefObject
    {
        /// <summary>
        /// 默认应用程序域
        /// </summary>
        public static AppDomain MainAppDomain { get; set; }
        /// <summary>
        /// 当前代理应用程序域
        /// </summary>
        public static AppDomain CurrentAppDomain { get; set; }
        /// <summary>
        /// 默认应用程序域的代理
        /// </summary>
        public static ProxyDomainObject MainProxy
        {
            get
            {
                AppDomain domain;
                if (MainAppDomain == null)
                {
                    domain = AppDomain.CurrentDomain;
                }
                else
                {
                    domain = MainAppDomain;
                }
                return (ProxyDomainObject)domain.CreateInstanceFromAndUnwrap(domain.SetupInformation.ApplicationBase + domain.SetupInformation.ApplicationName, typeof(ProxyDomainObject).FullName);
            }
        }
        private static readonly Dictionary<string, AppDomain> _pairAppDomains = new Dictionary<string, AppDomain>();
    
        private Assembly _assembly;
        public ProxyDomainObject()
        {
            _assembly = null;
        }
        public override object InitializeLifetimeService()
        {
            //return base.InitializeLifetimeService(); //实例的内部对象会在5分钟内被runtime释放
            return null; //将对象的租用周期改变为无限
        }
    
        public void LoadAssembly(string assemblyName = null)
        {
            if (string.IsNullOrEmpty(assemblyName))
            {
                return;
            }
            try
            {
                if (_assembly == null)
                {
                    var assRef = AssemblyName.GetAssemblyName(assemblyName);
                    _assembly = Assembly.Load(assRef);
                    Console.WriteLine($"{CurrentAppDomain.Id}.................assembly NULL,执行加载dll");
                }
                else
                {
                    Console.WriteLine($"{CurrentAppDomain.Id}.................assembly有,不加载dll");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
    
        }
        public object CreateInstance(string fullName, params object[] args)
        {
            if (_assembly == null)
            {
                return null;
            }
            return _assembly.CreateInstance(fullName, true, BindingFlags.Instance | BindingFlags.CreateInstance | BindingFlags.Public, Type.DefaultBinder, args, null, null);
        }
        public object Invoke(string className, string methodName, params object[] args)
        {
            if (_assembly == null)
            {
                return null;
            }
            var type = _assembly.GetType(className);
            if (type == null)
            {
                return null;
            }
            var method = type.GetMethod(methodName);
            if (method == null)
            {
                return null;
            }
            var obj = Activator.CreateInstance(type);
            return method.Invoke(obj, args);
        }
    
        public void SetDomainDelegate(AppDomain domain, AppDomain parentDomain)
        {
            CurrentAppDomain = domain;
            MainAppDomain = parentDomain;
            var crossAppDomainDelegate = new CrossAppDomainDelegate(MyCallBack);
            domain.UnhandledException += Domain_UnhandledException; ;
            domain.DoCallBack(crossAppDomainDelegate);
        }
    
        private void Domain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject is Exception ex)
            {
                LocalParking.LogFactory.Error(ex.Message, ex);
            }
        }
    
    
        private void MyCallBack()
        {
            Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
        }
    
        private void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
        }
    
    
        /// <summary>
        /// 是否已有指定名称的应用程序域
        /// True 有
        /// </summary>
        /// <param name="friendlyName"></param>
        /// <returns></returns>
        private static bool IsContainsAppDomain(string friendlyName)
        {
            return _pairAppDomains.ContainsKey(friendlyName);
        }
        public static AppDomain GetSiblingDomain(string friendlyName)
        {
            if (string.IsNullOrEmpty(friendlyName))
            {
                return null;
            }
            if (IsContainsAppDomain(friendlyName))
            {
                return _pairAppDomains[friendlyName];
            }
            return null;
        }
        /// <summary>
        /// 创建其他应用程序域
        /// </summary>
        /// <param name="parentDomain">当前应用程序域,一般是当前默认程序域</param>
        /// <param name="siblingDomainName">其他应用程序域名称</param>
        /// <returns></returns>
        public static AppDomain BuildSiblingDomain(AppDomain parentDomain, string siblingDomainName = null)
        {
            if (string.IsNullOrEmpty(siblingDomainName))
            {
                siblingDomainName = Guid.NewGuid().ToString();
            }
            if (IsContainsAppDomain(siblingDomainName))
            {
                return _pairAppDomains[siblingDomainName];
            }
            var evidence = new Evidence(parentDomain.Evidence);
            AppDomainSetup ads = new AppDomainSetup
            {
                ApplicationName = "Shadow",
                //应用程序根目录
                ApplicationBase = parentDomain.BaseDirectory,
            };
    
            //子目录(相对形式)在AppDomainSetup中加入外部程序集的所在目录,多个目录用分号间隔
            //ads.PrivateBinPath = assemblyPlugs;
            //设置缓存目录
            ads.CachePath = ads.ApplicationBase;
            //获取或设置指示影像复制是打开还是关闭
            ads.ShadowCopyFiles = "true";
            //获取或设置目录的名称,这些目录包含要影像复制的程序集
            ads.ShadowCopyDirectories = ads.ApplicationBase;
    
            ads.DisallowBindingRedirects = false;
            ads.DisallowCodeDownload = true;
    
            ads.ConfigurationFile = parentDomain.SetupInformation.ConfigurationFile;
            var domain = AppDomain.CreateDomain(siblingDomainName, evidence, ads);
            _pairAppDomains.Add(siblingDomainName, domain);
            return domain;
        }
    
        public void RemoveSiblingDomain(string siblingDomainName)
        {
            Console.WriteLine("所有域:" + _pairAppDomains.Count);
            foreach (var item in _pairAppDomains)
            {
                Console.WriteLine(item.Key);
            }
            Console.WriteLine(".................卸载当前域" + siblingDomainName);
            if (_pairAppDomains.ContainsKey(siblingDomainName))
            {
                Console.WriteLine(".................卸载当前域 exist " + siblingDomainName);
                var rslt = _pairAppDomains[siblingDomainName];
    
                _pairAppDomains.Remove(siblingDomainName);
                Console.WriteLine(".................卸载当前域 Remove " + siblingDomainName);
                try
                {
                    AppDomain.Unload(rslt);
                    Console.WriteLine(".................卸载当前域 Unload " + siblingDomainName);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
    
                    Task.Yield().GetAwaiter().GetResult();
                    Console.WriteLine(ex.Message);
                    AppDomain.Unload(rslt); // again
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    Console.WriteLine($"{(CurrentAppDomain == null ? 0 : CurrentAppDomain.Id)}.................siblingDomainName");
                }
            }
            
        }
        
    }
    
  • 相关阅读:
    Vue大文件上传 vuesimpleloader分片上传到AWS S3
    如何把设备安全的接入AWS IoT(一)
    Vue大文件分片上传 直连AWS S3
    JAVA AWS 根据Dynamodb增删改查数据
    JAVA实现和AWS IOT订阅、发布MQTT消息
    AWS 使用总结及部分服务学习记录
    Vue 刷新组件
    Vue文件上传 自定义样式 Button按钮代替Input 并通过java上传(非分片)到AWS S3
    sql 去年,月
    json2【转】
  • 原文地址:https://www.cnblogs.com/wesson2019-blog/p/13948150.html
Copyright © 2020-2023  润新知