C# 应用程序域
在.NET中,每个应用程序域都是一个独立的执行环境,有自己的安全边界和上下文。当使用AppDomain.ExecuteAssembly方法在一个新的应用程序域中执行一个程序集时,这个程序集将会在新的应用程序域中加载和执行,而与原应用程序域隔离开来,两个应用程序域之间的交互是受到限制的。
默认情况下,新应用程序域中的程序集无法访问原应用程序域中的对象和资源。如果需要在不同的应用程序域之间进行通信,需要使用.NET提供的跨应用程序域通信(Cross-AppDomain Communication)机制,例如MarshalByRefObject和AppDomain.UnhandledException事件等。
如果需要在新应用程序域中执行某些操作并将结果返回给原应用程序域,可以使用Remoting或WCF等技术。其中,Remoting提供了一种透明的远程调用机制,可以使得应用程序域之间的调用像本地调用一样简单;而WCF则提供了更加通用的跨进程和跨网络通信机制,可以支持多种协议和格式,具有更高的灵活性和扩展性。
总之,在.NET中,新的应用程序域与原应用程序域之间的交互需要通过特定的机制来实现,具体实现方式取决于具体的场景和需求.
在.NET中,被调用的目标程序集必须是可执行的,这是因为在.NET中,应用程序域的基本单元是可执行程序集(Assembly),而非单个类或对象。应用程序域是.NET提供的一种隔离机制,可以在同一个进程中加载和执行多个不同的可执行程序集,从而实现应用程序的模块化和隔离。
当在应用程序域中调用一个程序集时,CLR会将其加载到应用程序域中,并在其中创建一个或多个AppDomain对象。这个AppDomain对象将会在应用程序域的边界内隔离程序集的执行环境,保证程序集的运行不会对应用程序域之外的其他部分产生影响,从而提高应用程序的安全性和可靠性。
因此,为了能够在应用程序域中加载和执行一个程序集,这个程序集必须是可执行的,即符合.NET可执行程序集的规范,包含符号表、元数据和IL代码等信息。只有这样,CLR才能够正确地解析和执行这个程序集,并将其隔离在应用程序域内部的执行环境中,同时与其他程序集和应用程序域进行交互和通信。
总之,在.NET中,被调用的目标程序集必须是可执行的,才能够被加载到应用程序域中进行隔离和执行。
在.NET中,AppDomain类提供了一个DoCallBack方法,可以在当前应用程序域中调用指定委托(Delegate)的方法,并将其委托到另一个应用程序域中执行。这个方法通常用于实现应用程序域之间的通信和协作,可以在不同的应用程序域之间传递数据和执行代码,从而实现应用程序的分布式和模块化。
public void DoCallBack(CrossAppDomainDelegate callBackDelegate);
其中,callBackDelegate参数是一个CrossAppDomainDelegate委托,表示要在另一个应用程序域中执行的方法。该委托的参数和返回值必须是序列化和可传递的类型,否则将无法在应用程序域之间进行传递。
使用DoCallBack方法在新应用程序域中执行一个委托。这个委托输出了当前应用程序域的名称,并通过AppDomain.SetData方法将数据传递回主应用程序域。需要注意的是,在使用DoCallBack方法时,委托中的代码将会在另一个应用程序域中执行,因此需要考虑到数据和代码的传递和隔离问题。同时,由于跨应用程序域调用涉及到数据序列化和传输,因此可能会对性能和可靠性产生一定的影响。
AppDomain newDomain = AppDomain.CreateDomain("JohnYang New Domain");
Console.WriteLine(AppDomain.CurrentDomain.FriendlyName+","+AppDomain.CurrentDomain.IsDefaultAppDomain());
newDomain.SetData("Data", "Hello in new Domain");//在新应用程序域中设置槽
newDomain.DoCallBack(() =>
{
//这些代码在newDomain中执行
Console.WriteLine($"this is in {AppDomain.CurrentDomain.FriendlyName},{AppDomain.CurrentDomain.IsDefaultAppDomain()}");
var data = AppDomain.CurrentDomain.GetData("Data");//newDomain自身设置Data
Console.WriteLine($"new domain get data:{data}");//newDomain自身获取Data
});
//主程序域获取不到该项
Console.WriteLine($"{AppDomain.CurrentDomain.FriendlyName}获取"+AppDomain.CurrentDomain.GetData("Data"));
AppDomain.Unload(newDomain);
Console.ReadLine();
output:
Learn.exe,True
this is in JohnYang New Domain,False
new domain get data:Hello in new Domain
EasyBimBackend.exe获取
以下代码证明,独立应用程序域中,每个应用程序域都有自己的内存空间和运行环境,不同的应用程序域之间相互隔离,无法直接相互访问。因此,即使是同一个类的静态成员,也不能在不同的应用程序域之间相互访问。
class ProgramA
{
public static int count;
static void Main()
{
var domain = AppDomain.CreateDomain("JohnYang new domain");
domain.DoCallBack(() =>
{
ProgramA.count = 100;
});
Console.WriteLine(ProgramA.count);//打印0
Console.ReadLine();
}
}
在 MarshalByRefObject 对象之间进行远程调用时,数据流通常是单向的,即从客户端应用程序域到服务器应用程序域。但是,通过将一个 MarshalByRefObject 对象传递给另一个 MarshalByRefObject 对象的方法作为参数,可以实现远程过程调用的逆向。
具体来说,当 FooA 对象的方法接受一个 MarshalByRefObject 参数时,可以将另一个可远程访问的对象作为参数传递进来。这个参数对象在客户端应用程序域中创建,但是由于它继承自 MarshalByRefObject,所以客户端应用程序域中的代理对象将会在服务器应用程序域中创建一个真实的对象,然后将该对象作为参数传递给服务器应用程序域中的方法。
因此,逆向的 Remoting 过程是指在远程过程调用中,数据流向是从服务器应用程序域到客户端应用程序域。这使得客户端应用程序可以向服务器应用程序传递对象,从而实现更灵活和动态的交互。
public class FooA : MarshalByRefObject
{
public string SayHello(FooB b) => $"Hello from {AppDomain.CurrentDomain.FriendlyName}. FooB says: {b.SayHello()}";
}
public class FooB : MarshalByRefObject
{
public string SayHello() => $"Hello from {AppDomain.CurrentDomain.FriendlyName}";
}
class ProgramA
{
static void Main()
{
AppDomain newDomainA = AppDomain.CreateDomain("new domain A");
AppDomain newDomainB = AppDomain.CreateDomain("new domain B");
FooA fooA = (FooA)newDomainA.CreateInstanceAndUnwrap(typeof(FooA).Assembly.FullName, typeof(FooA).FullName);
//FooB fooB = (FooB)newDomainB.CreateInstanceAndUnwrap(typeof(FooB).Assembly.FullName, typeof(FooB).FullName);
FooB fooB = new FooB();
Console.WriteLine(fooA.SayHello(fooB)); // 在客户端应用程序域中调用FooA对象的方法,并将FooB对象作为参数传递进去
AppDomain.Unload(newDomainA);
AppDomain.Unload(newDomainB);
Console.ReadLine();
}
}
output:
Hello from new domain A. FooB says: Hello from Learn.exe
public class FooA : MarshalByRefObject
{
public string SayHello(FooB b) => $"Hello from {AppDomain.CurrentDomain.FriendlyName}. FooB says: {b.SayHello()}";
}
public class FooB : MarshalByRefObject
{
public string SayHello() => $"Hello from {AppDomain.CurrentDomain.FriendlyName}";
}
class ProgramA
{
static void Main()
{
AppDomain newDomainA = AppDomain.CreateDomain("new domain A");
AppDomain newDomainB = AppDomain.CreateDomain("new domain B");
FooA fooA = (FooA)newDomainA.CreateInstanceAndUnwrap(typeof(FooA).Assembly.FullName, typeof(FooA).FullName);
FooB fooB = (FooB)newDomainB.CreateInstanceAndUnwrap(typeof(FooB).Assembly.FullName, typeof(FooB).FullName);
//FooB fooB = new FooB();
Console.WriteLine(fooA.SayHello(fooB)); // 在客户端应用程序域中调用FooA对象的方法,并将FooB对象作为参数传递进去
AppDomain.Unload(newDomainA);
AppDomain.Unload(newDomainB);
Console.ReadLine();
}
}
output:
Hello from new domain A. FooB says: Hello from new domain B
C# 应用程序域的更多相关文章
- 【.net 深呼吸】跨应用程序域执行程序集
应用程序域,你在网上可以查到它的定义,凡是概念性的东西,大伙儿只需要会搜索就行,内容看了就罢,不用去记忆,更不用去背,“名词解释”是大学考试里面最无聊最没水平的题型. 简单地说,应用程序域让你可以在一 ...
- .NET应用程序域
在.NET平台下,可执行程序并没有直接承载在Windows进程中,而非托管程序是直接承载的..NET可执行程序承载在进程的一个逻辑分区中,称之为应用程序域(AppDomain).一个进程可以包含多个应 ...
- 读 《.Net 之美》解析.Net Remoting (应用程序域)-- Part.1
读 <.Net 之美>解析.Net Remoting (应用程序域)-Part1 理解 .Net Remoting 前言: 看张子阳老师的文章,总是给自己很大的信心,这个专题基本上以张老师 ...
- 跨应用程序域(AppDomain)的单例(Singleton)实现
转载自: 跨应用程序域(AppDomain)的单例(Singleton)实现 - CorePlex代码库 - CorePlex官方网站,Visual Studio插件,代码大全,代码仓库,代码整理,分 ...
- C#学习笔记----AppDomain应用程序域
使用.Net建立的可执行程序*.exe,并没有直接承载到进程当中,而是承载到应用程序域(AppDomain)当中.应用程序域是.Net引入的一个新概念,它比进程所占用的资源要少,可以被看做是一个轻量级 ...
- [转]C#综合揭秘——细说进程、应用程序域与上下文之间的关系
引言 本文主要是介绍进程(Process).应用程序域(AppDomain)..NET上下文(Context)的概念与操作.虽然在一般的开发当中这三者并不常用,但熟悉三者的关系,深入了解其作用,对提高 ...
- [ActionScript 3.0] AS3.0 Loader加载子swf时是否需要指定新的应用程序域ApplicationDomain
实际应用中, Loader加载子swf时是否需要指定新的应用程序域ApplicationDomain,需要择情况而定. 1.如果在本地将项目位置添加到flashplayer受信任位置(上一篇文章所述) ...
- [ActionScript 3.0] AS3 深入理解Flash的 应用程序域Application Domains
简介 网上有很多flash,通常都不需要显示的使用应用程序域,因为默认的应用程序域就够用了.其实复杂的情况下需要用到应用程序域,比如说有两个不同的swf,一个是旧版本的,一个是新版的,这两个文件里的类 ...
- 应用程序域(Application Domain)
应用程序域为隔离正在运行的应用程序提供了一种灵活而安全的方法. 应用程序域通常由运行时宿主创建和操作. 有时,您可能希望应用程序以编程方式与应用程序域交互,例如想在不停止应用程序运行的情况下卸载某个组 ...
- AppDomain 应用程序域
应用程序域 一.什么是应用程序域? 应用程序域 (application domain) (AppDomain) 一种边界,它由公共语言运行库围绕同一应用程序范围内创建的对象建立(即,从应用程序入口点 ...
随机推荐
- Qt QString的格式化与QString的拼接
1. QString 与 QString 直接用 + 号也可以 QString date = "昨晚"; QString msg = "你真棒": QStrin ...
- WPF无边框的一个方案(保留默认窗口的拖动、阴影等效果)
使用 WindowStyle="None" AllowsTransparency="True" 的方式达成无边框的效果有很多无法忽视的缺陷,比如失去了拖动效果. ...
- 配置tmux默认shell使用fish
设置tmux创建新窗口的时候的默认的shell类型 编写~/.tmux.conf文件 set-option -g default-shell /usr/bin/fish # 或者你想要的任何其他 sh ...
- Docker之一简介
什么是Docker Docker是Google使用go语言进行开发的,对进程进行封装隔离,始于操作系统层面的虚拟化技术. 因为隔离的进程独立于宿主机和其它的隔离进程,因此成为容器 Docker在容器的 ...
- maven知识理解和生命周期
学习的技能/知识 运动 提升 不足 强化了maven的知识理解和生命周期 3公里日常跑,其中1公里破之前的记录达到3分40 没有赖床,嗯:写完的博客自己阅读又温习了一遍 下午没课,但都用来休息了.. ...
- .NET周刊【3月第3期 2025-03-16】
国内文章 在 VisualStudio 一键 F5 启动调试 Roslyn 分析器项目 https://www.cnblogs.com/lindexi/p/18730521 本文将告诉大家如何在 Vi ...
- centos简单文件备份
1. 背景 现在有一个正在使用的服务器, 需要对服务器上的数据库数据.实验室文件以及采购平台文件进行备份, 将备份文件存储到另外一个服务器上, 要求留存最近七天的备份文件. 2.详细步骤 2.1 备份 ...
- springboot 集成Swagger2报错 Failed to start bean ‘documentationPluginsBootstrapper’; nested exception is
springboot 集成Swagger2报错 Failed to start bean 'documentationPluginsBootstrapper'; nested exception is ...
- Sa-Token v1.42.0 发布 🚀,新增 API Key、TOTP 验证码、RefreshToken 反查等能力
Sa-Token 是一款 免费.开源 的轻量级 Java 权限认证框架,主要解决:登录认证.权限认证.单点登录.OAuth2.0.微服务网关鉴权 等一系列权限相关问题. 目前最新版本 v1.42.0 ...
- 如何对 Java 的垃圾回收进行调优?
如何对 Java 的垃圾回收进行调优? Java 垃圾回收的调优涉及多个方面,从选择合适的垃圾回收器到调整堆内存的大小.配置 GC 参数等,下面是一些常见的调优方法: 1. 选择合适的垃圾回收器 不同 ...