Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 不同AppDomain中的数据是如何组织的,我如何跨域访问它们_C#_Module_Appdomain - Fatal编程技术网

C# 不同AppDomain中的数据是如何组织的,我如何跨域访问它们

C# 不同AppDomain中的数据是如何组织的,我如何跨域访问它们,c#,module,appdomain,C#,Module,Appdomain,嗨,我有一个由一些“内核”和模块组成的应用程序,这些模块动态加载到自己的AppDomain中,并根据需要卸载。但我不明白一件事。我将发布一个与我所拥有的类似的简单代码 有一个“接口”类,它包含许多虚拟钩子和属性以及一些自己的函数: [Serializable()] public abstract class Module : MarshalByRefObject { public static List<Module> module = new List<Module&

嗨,我有一个由一些“内核”和模块组成的应用程序,这些模块动态加载到自己的AppDomain中,并根据需要卸载。但我不明白一件事。我将发布一个与我所拥有的类似的简单代码

有一个“接口”类,它包含许多虚拟钩子和属性以及一些自己的函数:

[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中)

静力学是最重要的!每个AppDomain将有不同的模块列表。

您需要能够实例化每个目标域的代理,并跨应用程序域边界传递它们。我将创建一个控制器模式,用于管理每个远程域中当前域的所有模块,并在需要操作数据时跨域边界传递代理

下面是一个如何使用跨多个域操纵对象的示例

命名空间控制台应用程序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;
        }
    }
}