如何组织不同AppDomain中的数据以及如何跨域访问它们

时间:2012-11-13 10:47:41

标签: c# module appdomain

您好我有一些应用程序,包含一些“内核”和动态加载到自己的AppDomain并根据需要卸载的模块。但我不明白一件事。我将发布一个类似于我的简单代码。

“interface”是一个包含大量虚拟钩子和属性以及一些自己的函数的类:

[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
    }
}

每个模块都是一个引用核心的新项目,并创建一个继承自Module并扩展“内核”的新类。一些事件被挂钩,我通过Module.module List进入循环,该List应该包含所有现有的已加载实例,并在该实例中调用相应的钩子。如果我在一个AppDomain中,这可以正常工作。但是,如果我为模块使用单独的AppDomain,似乎原始域的内存被复制到新域,当我调用新实例的构造函数时,它不会将自身插入到原始域的Module.module中的静态数组中,但是它将自身插入到新域中的Module.module中。这意味着,在核心中,我仍然在Module.module中有0个模块。我设法通过创建另一个注册模块而不是我在构造函数中的函数来解决这个问题。但有时我会访问原始域中的内存,有时还会访问模块新域中的内存。这会引起麻烦。我怎样才能确保我总是从内核和模块访问相同的内存?

我需要做的例子是:

  • 将指向AppDomain A内存类的实例的指针传递给生活在AppDomain B中的模块的钩子
  • 让模块更改该类中的内容(在域A的内存中,而不是在B中)

2 个答案:

答案 0 :(得分:0)

静力学是not shared by AppDomains!每个AppDomain都有不同的模块列表。

答案 1 :(得分:0)

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

以下是如何使用AppDomainToolkit跨多个域操纵对象的示例。

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;
        }
    }
}

Output