zoukankan      html  css  js  c++  java
  • 《CLR via C#》 第22章 CLR寄宿和AppDomain 跨越AppDomain边界访问对象

    跨越AppDomain边界访问对象

    将书中的代码(3处)将“MarshalByRefType”修改为“typeof(MarshalByRefType).FullName”,即可得到书中的输出结果:

    将:MarshalByRefType mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly,“MarshalByRefType”);

    修改为:MarshalByRefType mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, typeof(MarshalByRefType).FullName);

    修改后的代码为:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Reflection;
    using System.Runtime.Remoting;

    namespace CLRAppDomain
    {
    public class Marshal
    {
    private static void Marshaling()
    {
    //获取AppDomain的一个引用(“调用线程”在该AppDomain中执行)
    AppDomain adCallingThreadDomain = Thread.GetDomain();
    //每个AppDomain都有一个友好字符串名称,获取这个名称并显示
    string callingDomainName = adCallingThreadDomain.FriendlyName;
    Console.WriteLine("Defalut AppDomain's friendly name={0}", callingDomainName);
    //获取&显示我们的AppDomain中包含“Main”方法的程序集
    string exeAssembly = Assembly.GetEntryAssembly().FullName;
    Console.WriteLine("Main assembly={0}", exeAssembly);

    //定义一个局部变量引用一个AppDomain
    //*** Demo 1,使用Marshal-by-Reference进行跨AppDomain通信 ***
    Console.WriteLine("{0}*** Demo #1", Environment.NewLine);
    //新建一个AppDomain,安全性和配置匹配与当前的AppDomain
    AppDomain ad2 = AppDomain.CreateDomain("AD #2", null, null);
    //将我们的程序集加载到AppDomain中,构造一个对象,把它封送会我们的AppDomain
    //实际上得到的是一个代理引用
    MarshalByRefType mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, typeof(MarshalByRefType).FullName);
    Console.WriteLine("Type={0}", mbrt.GetType());//这里CLR在类型上撒谎了,得到Type=AppDomainLib.MashalByRefType,其实并不是这样
    //证明得到的是一个代理的引用
    Console.WriteLine("Is Proxy={0}", RemotingServices.IsTransparentProxy(mbrt));
    //看起来像是在MashalByRefType上调用了一个方法,实在不然
    //我们是在代理类型上调用了一个方法,代理使线程切换至拥有对象
    //的那个AppDomain
    mbrt.SomeMehtod();
    //卸载新的AppDomain
    AppDomain.Unload(ad2);
    //mbrt引用了一个无效的代理对象,代理对象引用了一个无效的AppDomain
    try
    {
    mbrt.SomeMehtod();
    }
    catch (AppDomainUnloadedException)
    {
    Console.WriteLine("Fall Call");
    }
    //*** Demo 2,使用Marshal-by-Value进行跨AppDomain通信 ***
    Console.WriteLine("{0}*** Demo #2", Environment.NewLine);

    //新建一个AppDomain,安全性和配置匹配与当前的AppDomain
    ad2 = AppDomain.CreateDomain("AD #2", null, null);
    //将我们的程序集加载到AppDomain中,构造一个对象,把它封送会我们的AppDomain
    //实际上得到的是一个代理引用
    mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, typeof(MarshalByRefType).FullName);
    //对象的方法返回所返回对象的一个副本
    //返回的对象是按值(而非引用)封送
    MarshalByValType mbv = mbrt.MethodWidthReturn();
    //证明我们得到的不是对一个代理对象的引用
    Console.WriteLine("Is Porxy={0}", RemotingServices.IsTransparentProxy(mbv));
    //看起来像是在MarshalByValType上调用方法,事实确实如此
    Console.WriteLine("Return Object create:{0}", mbv.ToString());
    //卸载AppDomain
    AppDomain.Unload(ad2);
    //mbv引用有效的对象,卸载AppDomain没有影响
    try
    {
    //我们是在对象上调用一个方法,所有不会抛出异常
    Console.WriteLine("Return Object create:{0}", mbv.ToString());
    }
    catch (AppDomainUnloadedException)
    {
    Console.WriteLine("Fail Call");
    }

    //*** Demo 3 使用不可封送的类型进行AppDomain通信 ****
    Console.WriteLine("{0}*** Demo #3", Environment.NewLine);
    //新建一个AppDomain,安全性和配置匹配与当前的AppDomain
    ad2 = AppDomain.CreateDomain("AD #2", null, null);
    //将我们的程序集加载到AppDomain中,构造一个对象,把它封送会我们的AppDomain
    //实际上得到的是一个代理引用
    mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, typeof(MarshalByRefType).FullName);
    //对象的方法返回一个不可封送的对象,抛出异常
    NonMarshalableType nmt = mbrt.MethodArgAndReturn(callingDomainName);
    //这里的代码永远执行不到。。。
    }
    public static void Main()
    {
    Marshaling();
    }
    }

    // 该类的实例可跨越AppDomain的边界“按引用封送”
    public sealed class MarshalByRefType : MarshalByRefObject
    {
    public MarshalByRefType()
    {
    Console.WriteLine("{0} .ctor running in {1}", this.GetType().Name, Thread.GetDomain().FriendlyName);
    }
    public void SomeMehtod()
    {
    Console.WriteLine("Executing is " + Thread.GetDomain().FriendlyName);
    }
    public MarshalByValType MethodWidthReturn()
    {
    Console.WriteLine("Executing is " + Thread.GetDomain().FriendlyName);
    MarshalByValType t = new MarshalByValType();
    return t;
    }
    public NonMarshalableType MethodArgAndReturn(string callingDomainName)
    {
    // 注意callingDomainName是可以序列化的
    Console.WriteLine("Calling from {0} to {1} ", callingDomainName, Thread.GetDomain().FriendlyName);
    NonMarshalableType t = new NonMarshalableType();
    return t;
    }
    }

    // 该类的实例可跨越AppDomain的边界“按值封送”
    [Serializable]
    public sealed class MarshalByValType : Object
    {
    private DateTime m_CreateTime = DateTime.Now;//注意DateTime是可序列化的
    public MarshalByValType()
    {
    Console.WriteLine("{0} ctor running in {1},create on {2}", this.GetType().ToString(),
    Thread.GetDomain().FriendlyName, m_CreateTime);
    }
    public override string ToString()
    {
    return m_CreateTime.ToLongDateString();
    }
    }

    // 该类的实例不可跨越AppDomain进行封送
    //[Serializable]
    public sealed class NonMarshalableType : Object
    {
    public NonMarshalableType()
    {
    Console.WriteLine("Executing in {0}", Thread.GetDomain().FriendlyName);
    }
    }

    }

  • 相关阅读:
    如何在一个项目中同时包含mvc建站、webapi接口
    解决api、WebService跨域问题
    mvc接口、webapi、webservice 对比
    云服务器 远程mysql 无法连接
    c#快速写本地日志
    使用筛选器特性标记方法解决webapi 跨域问题
    流量控制(滑动窗口协议)
    解释Windows7“上帝模式”的原理
    Linux网络协议栈(二)——套接字缓存(socket buffer)
    理解MySQL——架构与概念
  • 原文地址:https://www.cnblogs.com/zhangtingzu/p/5484802.html
Copyright © 2011-2022 走看看