C# 不同AppDomain中的数据是如何组织的,我如何跨域访问它们
嗨,我有一个由一些“内核”和模块组成的应用程序,这些模块动态加载到自己的AppDomain中,并根据需要卸载。但我不明白一件事。我将发布一个与我所拥有的类似的简单代码 有一个“接口”类,它包含许多虚拟钩子和属性以及一些自己的函数:C# 不同AppDomain中的数据是如何组织的,我如何跨域访问它们,c#,module,appdomain,C#,Module,Appdomain,嗨,我有一个由一些“内核”和模块组成的应用程序,这些模块动态加载到自己的AppDomain中,并根据需要卸载。但我不明白一件事。我将发布一个与我所拥有的类似的简单代码 有一个“接口”类,它包含许多虚拟钩子和属性以及一些自己的函数: [Serializable()] public abstract class Module : MarshalByRefObject { public static List<Module> module = new List<Module&
[Serializable()]
public abstract class Module : MarshalByRefObject
{
public static List<Module> module = new List<Module>();
public string Name = "";
public string Version = "unknown";
public DateTime Date = DateTime.Now;
Module()
{
lock(module)
{
module.Add(this);
}
}
~Module()
{
Exit();
lock (module)
{
if (module.Contains(this))
{
module.Remove(this);
}
}
core.Log("Module was unloaded: " + this.Name);
}
public virtual void Hook1()
{
// by default ignore
}
}
[Serializable()]
公共抽象类模块:MarshalByRefObject
{
公共静态列表模块=新建列表();
公共字符串名称=”;
公共字符串Version=“未知”;
public DateTime Date=DateTime.Now;
模块()
{
锁(模块)
{
模块。添加(本);
}
}
~Module()
{
退出();
锁(模块)
{
if(模块包含(此))
{
模块。移除(此);
}
}
Log(“模块已卸载:+this.Name”);
}
公共虚拟空间1()
{
//默认情况下忽略
}
}
每个模块都是一个新项目,它引用到核心,并创建一个新类,该类从模块继承并扩展“内核”。有些事件是以一种我在Module.Module列表中循环的方式钩住的,该列表应该包含所有现有的已加载实例,并在其中调用相应的钩子。如果我在一个AppDomain中,这可以正常工作。但是,如果我对模块使用单独的AppDomain,则似乎原始域的内存被复制到了新域,并且当我调用新实例的构造函数时,它不会将自身插入到原始域的module.module中的静态数组中,而是将自身插入到新域中的module.module中。这意味着,在内核中,Module.Module中仍然有0个模块。我设法通过创建另一个注册模块的函数来解决这个问题,而不是在构造函数中注册模块。但有时我访问原始域中的内存,有时访问模块的新域中的内存。这会引起麻烦。如何确保始终从内核和模块访问相同的内存
我需要做的示例是:
- 将指向AppDomain a内存中的类实例的指针传递给AppDomain B中的模块挂钩
- 让模块更改该类中的某些内容(在域A的内存中,而不是在B中)
命名空间控制台应用程序1
{
使用制度;
使用System.Threading.Tasks;
使用AppDomainToolkit;
使用System.Collections.Generic;
班级计划
{
静态void Main(字符串[]参数)
{
使用(var context1=AppDomainContext.Create())
使用(var context2=AppDomainContext.Create())
使用(var context3=AppDomainContext.Create())
{
var pizzaintext1=Remote.CreateProxy(context1.Domain,“夏威夷”);
//从当前应用程序域操纵对象
PizzainText1.RemoteObject.AddTopping(新的Topping(“奶酪”);
//从上下文2操纵对象
RemoteAction.Invoke(
上下文2.域,
PizzainText1.RemoteObject,
新配料(“菠萝”),
(比萨饼、配料)=>
{
比萨饼。添加配料(配料);
});
//操纵对象,从上下文3添加信息
RemoteAction.Invoke(
上下文3.域,
PizzainText1.RemoteObject,
(比萨饼)=>
{
比萨饼。添加配料(新配料(“火腿”);
});
Console.WriteLine(pizzaintext1.RemoteObject.ToString());
}
Console.ReadKey();
}
}
班级比萨饼:MarshallByRefObject
{
私有只读IList浇头;
公共比萨饼(字符串名称)
{
this.Name=Name;
this.toppings=新列表();
}
公共字符串名称{get;private set;}
公共空白添加顶部(顶部顶部)
{
这个。浇头。添加(浇头);
}
公共重写字符串ToString()
{
var pizza=this.Name+“带浇头:[”;
for(int i=0;i
为什么将该类标记为可序列化?MarshallByErrorObject派生对象是位于一个AppDomain上并通过代理(由.NET远程处理隐式创建)从另一个AppDomain访问的对象。应将Serializable属性添加到对象从一个AppDomain传递到另一个AppDomain的所有类中。这些对象通常是MarshalByRefObject方法的参数或返回值。此外,如果您添加创建/访问模块对象的代码,将更容易获得帮助。@PanosRontogiannis
namespace ConsoleApplication1
{
using System;
using System.Threading.Tasks;
using AppDomainToolkit;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
using (var context1 = AppDomainContext.Create())
using (var context2 = AppDomainContext.Create())
using (var context3 = AppDomainContext.Create())
{
var pizzaInContext1 = Remote<Pizza>.CreateProxy(context1.Domain, "Hawaiian");
// manipulate object from current app domain
pizzaInContext1.RemoteObject.AddTopping(new Topping("Cheese"));
// manipulate object from context 2
RemoteAction.Invoke(
context2.Domain,
pizzaInContext1.RemoteObject,
new Topping("Pineapple"),
(pizza, topping) =>
{
pizza.AddTopping(topping);
});
// manipulate object, adding info from context 3
RemoteAction.Invoke(
context3.Domain,
pizzaInContext1.RemoteObject,
(pizza) =>
{
pizza.AddTopping(new Topping("Ham"));
});
Console.WriteLine(pizzaInContext1.RemoteObject.ToString());
}
Console.ReadKey();
}
}
class Pizza : MarshalByRefObject
{
private readonly IList<Topping> toppings;
public Pizza(string name)
{
this.Name = name;
this.toppings = new List<Topping>();
}
public string Name { get; private set; }
public void AddTopping(Topping topping)
{
this.toppings.Add(topping);
}
public override string ToString()
{
var pizza = this.Name + " with toppings: [";
for (int i = 0; i < this.toppings.Count; i++)
{
pizza += this.toppings[i].Name;
if (i < this.toppings.Count - 1)
{
pizza += ",";
}
}
pizza += "]";
return pizza;
}
}
[Serializable]
class Topping
{
public Topping(string name)
{
this.Name = name;
}
public string Name { get; private set; }
public override string ToString()
{
return this.Name;
}
}
}