当前位置: 移动技术网 > IT编程>开发语言>.net > 学习.NET中的AppDomain

学习.NET中的AppDomain

2018年03月07日  | 移动技术网IT编程  | 我要评论

意外之夫,邱会作回忆录 pdf,jquery find

什么是AppDomain?
AppDomain是一组程序集的逻辑容器,AppDomain是为了提供隔离而设计的。它提供了保护、配置和终止其中每一个应用程序的隔离

AppDomain的功能:

1.一个AppDomain中的对象不能直接访问另一个Appdomain中的对象

 一个AppDomain中的代码创建对象后,则这个对象就被创建他的AppDomain所拥有,它的生存期不能超过拥有它的AppDomain,要想访问另一个AppDomain中的对象

只能使用按引用传送或按值传送的语义。这就强制建立了清晰的分隔和边界,这种隔离是AppDomain很容易从进程卸载,而不影响其他运行的AppDomain。

2.AppDomain可以被卸载

CLR不支持从AppDomain中卸载特定的程序集。但可以告诉CLR卸载一个AppDomain,从而卸载AppDomain中包含的所有程序集。

3.AppDomain可以单独保护

AppDomain创建以后会应用一个权限集,它决定了向运行在这个AppDomain中运行代码的最大权限

4.AppDomain可以配置

AppDomain创建后会关联一组配置,这些配置主要影响AppDomain加载程序集的方式。

如何跨AppDomain访问对象?

一个AppDomain要和另一个AppDomain中的类型和对象通信,只能通过良好定义的机制进行。

以下代码演示了如何创建AppDomain、在其中加载程序集并构造程序集定义的类型的实例。演示了以下三种类型在构造时的不同行为:
”按引用封送“(Marshal-By-Reference)类型,“按值封送”类型(Marshal-By-Value)以及完全不能封送的类型

    class Program
    {
        static void Main(string[] args)
        {
            var a = Thread.GetDomain();
            string callingDomianName = Thread.GetDomain().FriendlyName;
            AppDomain a2 = AppDomain.CreateDomain("a2");
            string exeAssembly = Assembly.GetEntryAssembly().FullName;

            //Demo1***使用Marshal-by-reference进行跨域通信***
            Console.WriteLine("{0}#Demo1", Environment.NewLine);
            MarshalByRefType mbrt = null;
            mbrt = (MarshalByRefType)a2.CreateInstanceAndUnwrap(exeAssembly, "ConsoleApplication1.MarshalByRefType");
            //证明得到的是一个代理对象的引用
            Console.WriteLine("是否代理={0}", RemotingServices.IsTransparentProxy(mbrt));
            //看起来像是在MarshalByRefType上调用一个方法,其实不是
            //我们是在代理类型上调用方法,代理使应用切换到真是拥有对象的AppDomian
            //并在真实的对象上调用方法
            mbrt.SomeMethod();

            //卸载新的AppDomain
            AppDomain.Unload(a2);

            try
            {
                //mbrt引用一个有效的代理对象,代理对象引用一个无效的AppDomain
                mbrt.SomeMethod();
                Console.WriteLine("成功调用");
            }
            catch (AppDomainUnloadedException)
            {
                Console.WriteLine("调用失败");
            }

            //***Demo2:使用Marshal-By-Value进行跨AppDomain通信
            Console.WriteLine("{0}#Demo2", Environment.NewLine);

            a2 = AppDomain.CreateDomain("a2");
            mbrt = (MarshalByRefType)a2.CreateInstanceAndUnwrap(exeAssembly, "ConsoleApplication1.MarshalByRefType");
            //对象方法直接返回对象副本,对象按值封送
            MarshalByValType mbvt = mbrt.MethodWithReturn();

            //证明得到的不是对代理对象的引用
            Console.WriteLine("是否代理={0}", RemotingServices.IsTransparentProxy(mbvt));

            //看起来是在MarshalByValType中调用方法,实际上也是如此
            mbvt.ToString();
      
            //卸载新的Appdomain
            AppDomain.Unload(a2);

            try
            {
                //我们是在对象上调用一个方法,不会抛出异常
               mbvt.ToString();
               Console.WriteLine("成功调用");
            }
            catch (AppDomainUnloadedException)
            {
                Console.WriteLine("调用失败");
            }

            //***Demo3:使用不可封送的类型进行跨AppDomain的通信
            Console.WriteLine("{0}#Demo3", Environment.NewLine);
            a2 = AppDomain.CreateDomain("a2");
            mbrt = (MarshalByRefType)a2.CreateInstanceAndUnwrap(exeAssembly, "ConsoleApplication1.MarshalByRefType");
            //返回一个不可封送的对象,抛出异常
            try
            {
                NonMashalbleType nmt = mbrt.MethodArgAndReturn(callingDomianName);
            }
            catch (AppDomainUnloadedException ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadKey();    
        }
    }

    [Serializable]
    public sealed class MarshalByRefType : MarshalByRefObject
    {
        public MarshalByRefType()
        {
            Console.WriteLine("{0}的构造器在{1}中运行", this.GetType().ToString(), Thread.GetDomain().FriendlyName);
        }

        public void SomeMethod()
        {
            Console.WriteLine("在{0}中执行", Thread.GetDomain().FriendlyName);
        }

        public MarshalByValType MethodWithReturn()
        {
            Console.WriteLine("在{0}中执行", Thread.GetDomain().FriendlyName);
            MarshalByValType t = new MarshalByValType();
            return t;
        }

        public NonMashalbleType MethodArgAndReturn(string callingThreadName)
        {
            Console.WriteLine("来自{0}的调用", callingThreadName);
            NonMashalbleType t = new NonMashalbleType();
            return t;
        }
    }

    [Serializable]
    public sealed class MarshalByValType : Object
    {
        private DateTime m_time = DateTime.Now;

        public MarshalByValType()
        {
            Console.WriteLine("{0}的构造器在{1}中运行,创建于{2:D}", this.GetType().ToString(),
                Thread.GetDomain().FriendlyName, m_time);
        }

        public override string ToString()
        {
            return m_time.ToLongDateString();
        }
    }

    //不能封送的类型
    public sealed class NonMashalbleType
    {
        public NonMashalbleType()
        {
            Console.WriteLine("在{0}中执行", Thread.GetDomain().FriendlyName);
        }
    }

  

 以下是代码运行结果:

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网