.Net组件程序设计之远程调用(一)

.Net组件程序设计之远程调用(一)

 .Net组件程序设计之远程调用(一)

1应用程序域

我们知道我们写的C#代码是在操作系统逻辑体系结构中最上层的,然而操作系统本身是不会认识C#代码的,它只认识机器代码。那我们写的程序经过编译后是编译成IL的,是怎么运行的呢?实际是在一个托管的环境下运行的,是.NET提供的支持,操作系统是不会识别IL的,这中间就需要一个桥梁:应用程序域。操作系统中的进程是资源单位,应用程序域的执行使用当然也要占用空间使用资源了,所以是物理进程承载着应用程序域的,而且这种承载关系并不是一对一的。

图:应用程序域

.Net组件程序设计之远程调用(一)

使用应用程序域这样的机制,是有许多好处的。比如说客户端在调用其他组件的时候可以创建一个应用程序域,然后在新建的应用程序域中加载组件进行操作等等,即使被调用的组件发生一些致命的错误也不会导致客户端崩溃,有效的进行了错误隔离。还有一些数据交互传输上的性能差异等等,这里不做详细的阐述了。

2.NET Remoting

.NET Remoting是一种基于.NET平台的分布式系统框架,所了解的就是用于数据传输。 说几句它被使用的局限性很大,受到了平台的限制,当然如果仅仅是这样是不能否定它的强大和几乎无限扩展的框架体系,无论在哪一个环节你都可以自己来实现一些自定义的功能。会在下个篇幅稍作讲解。

3.AppDomain

在.NET中用AppDoMain类来表示应用程序域,也提供了获取当前应用程序域的方法,可以直接使用AppDoMain类的静态属性CurrentDomain来获取到当前程序所在的应用程序域,这是一种方法,还额外提供一种了,就是Thread类的GetDomain()静态方法也是可以获取到的。

3.1 在当前应用程序域中创建对象

 1 namespace RemoteServer
 2   public class class1
 3     {
 4         private string appDoMainName;
 5 
 6         public class1()
 7         {
 8             appDoMainName = AppDomain.CurrentDomain.FriendlyName;
 9         }
10 
11         public void Writer()
12         {
13             Console.WriteLine(appDoMainName);
14         }
15     }

class1中构造函数是获取当前应用程序域的名称,并且是在Writer()方法中输出到控制台界面中,

using RemoteServer;

namespace RemoteCase
{
            AppDomain appDoMain = AppDomain.CurrentDomain;
            class1 cls1 = (class1)appDoMain.CreateInstanceFromAndUnwrap("RemoteServer.dll", "RemoteServer.class1");
            cls1.Writer();
}

图3-1

.Net组件程序设计之远程调用(一)

这里使用了AppDomain中的静态方法CreateInstanceFromAndUnwrap(),因为当前项目已经引用了RemoteServer程序集,所以第一个参数只是一个显示的名称,并不是全路径,在调用方法的时候,应用程序域会加载程序集,用于获取到元数据。

3.2 在新建应用程序域中创建对象

 1 namespace RemoteServer
 2       public class class1:MarshalByRefObject
 3       {
 4         private string appDoMainName;
 5 
 6         public class1()
 7         {
 8             appDoMainName = AppDomain.CurrentDomain.FriendlyName;
 9         }
10 
11         public void Writer()
12         {
13             Console.WriteLine(appDoMainName);
14         }
15       }

1 using RemoteServer;
2 
3       AppDomain appDoMain = AppDomain.CurrentDomain;
4       AppDomain newDoMain = AppDomain.CreateDomain("NewDoMain");
5       class1 cls1 = (class1)newDoMain.CreateInstanceFromAndUnwrap("RemoteServer.dll", "RemoteServer.class1");
6       cls1.Writer();

图3-2
.Net组件程序设计之远程调用(一)

3.3 拆包远程对象

图3-3-1

.Net组件程序设计之远程调用(一)

这段代码是3.2中的代码,cls1并不是class1类型本身,而是代理,访问远程对象都是通过代理完成的,这么屌炸天的.NET当然提供优化,将创建远程对象和在客户端建立代理分离,这样可以在你创建了一个远程对象之后再建立代理。 AppDomain类提供了一套CreateInstance()方法来创建对象,但是都以ObjectHandle的形式返回一个远程对象句柄(意思就是远程对象的唯一标示,这个句柄能代表远程对象)

ObjectHandle对象实现了System.Runtime.Remoting命名空间下的IObjectHandle接口:

 1 namespace RemoteServer
 2 public class class1:MarshalByRefObject
 3     {
 4         private string appDoMainName;
 5 
 6         public class1()
 7         {
 8             appDoMainName = AppDomain.CurrentDomain.FriendlyName;
 9         }
10 
11         public void Writer()
12         {
13             Console.WriteLine(appDoMainName);
14         }
15 
16     }

 1 using RemoteServer;
 2 
 3             AppDomain appDoMain = AppDomain.CurrentDomain;
 4             AppDomain newDoMain = AppDomain.CreateDomain("NewDoMain");
 5             IObjectHandle objecthandle;
 6             objecthandle = newDoMain.CreateInstance("RemoteServer", "RemoteServer.class1");
 7 
 8             RemoteServer.class1 cls1 = objecthandle.Unwrap() as RemoteServer.class1;
 9 
10             cls1.Writer();

一般情况下是不需要手动拆包对象句柄的,这样做的好处只是可以推迟加载RemoteServer程序集,只有在 objecthandle.Unwrap()的时候才会建立代理,而建立代理必须需要对象元数据。

4远程对象类型

一般情况下,被引用对象和客户端同在一个应用程序域,这样的情况下不涉及到代理,也不会用到什么远程调用,

而是直接引用对象,如果当你需要调用另一个应用程序域里的对象时会是什么样的?默认情况下.NET是不允许对象跨应用程序域访问的,

不管是不是在同一个进程内。但是呢如果要访问,也不是不行的,.NET提供了两种数据传递方式,一种是值传递,一种是引用传递

4.1按值封送

   当应用程序域A调用应用程序域B中的对象时,应用程序域B中的对象会被拷贝一个克隆到应用程序域A,这时候两个对象是不存在任何关系的,这种情况叫做按值封送    一般情况下都是使类型使用Serializable特性,支持序列化,通过序列化来达到按值封送的目的,在被调用方序列化,到调用方反序列化。

4.2引用封送

   这种情况就是当应用程序域A调用应用程序域B的对象时,应用程序域A获得的是应用程序域B中对象的引用,

这个引用挂在哪里呢?挂在应用程序域A的对象代理上,这种情况就叫引用封送    引用封送就比按值封送有意思多了,想要满足可以引用封送的要求,则对象必须继承自MarshalByRefObject,MarshalByRefObject类型给出的解释就是 允许在支持远程处理的应用程序中跨应用程序域边界访问对象,这样作为它的子类同样的也享受这样的优待。在引用封送中会有两种远程对象激活模式,这个内容在下一个篇幅中会有详细的示例代码。

 

 

 

作者:金源

出处:http://www.cnblogs.com/jin-yuan/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面

转载于:https://www.cnblogs.com/jin-yuan/p/3756153.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109819.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • SQL 报错注入详解[通俗易懂]

    SQL 报错注入详解[通俗易懂]一、报错注入详解近期学习SQL报错注入,本篇文章为关于报错注入的一些个人理解,如有错误,希望指出本文使用sqli-labs数据库作为示例1、十种MySQL报错注入:报错注入方式有很多,其中比较常见的有floor()、extractvalue()、updatexml()三种,本篇文章主要对这三种进行分析,其他的请参考文章:十种MySQL报错注入2、floor()2.1、payload分析先贴上一个常见的payload再进行分析(sqli-labsLess-5)’

    2022年9月30日
    0
  • RuntimeException和Exception区别

    RuntimeException和Exception区别1.java将所有的错误封装为一个对象,其根本父类为Throwable,Throwable有两个子类:Error和Exception。2.Error是Throwable的子类,用于指示合理的应用程序不应该试图捕获的严重问题。大多数这样的错误都是异常条件。虽然ThreadDeath错误是一个“正规”的条件,但它也是Error的子类,因为大多数应用程序都不应该试图捕获它。在执行该方…

    2022年7月25日
    5
  • 免费好用的图片压缩网站,有这五个就够了(收藏备用)

    免费好用的图片压缩网站,有这五个就够了(收藏备用)前言当我们想要线上报名提交照片时,大小却超过范围,这时就需要压缩软件的帮助。但大多主流的软件可以压缩但想要下载就需要收费了,下面是五个国内外免费的压缩平台。一、OnlineImage优点:图片可以压缩90%以上,可以批量压缩,速度只需要几秒钟完全免费,无数量限制,支持绝大多数图片压缩格式缺点:不支持自定义图片大小压缩,广告比较多网站链接为:https://www.onlineimagetool.com/zh/二、Docsmall……

    2022年6月18日
    100
  • 实战:springboot整合rabbitMQ「建议收藏」

    实战:springboot整合rabbitMQ「建议收藏」一、RabbitMQ简述与其docker安装这里主要讲解实战整合rabbitMQ,了解RabbitMQ简述与其docker安装请点击:传送门二、springboot整合rabbitMQ1.新建springboot项目2.pom:主要添加以下两个依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-

    2022年5月14日
    38
  • Idea激活码最新教程2024.1.5版本,永久有效激活码,亲测可用,记得收藏

    Idea激活码最新教程2024.1.5版本,永久有效激活码,亲测可用,记得收藏Idea 激活码教程永久有效 2024 1 5 激活码教程 Windows 版永久激活 持续更新 Idea 激活码 2024 1 5 成功激活

    2025年5月28日
    0
  • jps命令的使用方法

    jps(JavaVirtualMachineProcessStatusTool)是java提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情况。很多人都是用过unix系统里的ps命令,这个命令主要是用来显示当前系统的进程情况,有哪些进程以及进程id。jps也是一样,它的作用是显示当前系统的java进程情况…

    2022年4月5日
    48

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号