1

こんにちは、いくつかの「カーネル」と、独自の 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
    }
}

各モジュールは、コアを参照する新しいプロジェクトであり、モジュールから継承されて「カーネル」を拡張する新しいクラスを作成します。一部のイベントは、既存のロードされたすべてのインスタンスを含むことになっている Module.module List をループして、その中でそれぞれのフックを呼び出す方法でフックされます。1 つの AppDomain にいる場合、これは正常に機能します。しかし、モジュールに別の AppDomain を使用すると、元のドメインのメモリが新しいドメインにコピーされるようで、新しいインスタンスのコンストラクターを呼び出すと、元のドメインの Module.module の静的配列に挿入されませんが、それ自体を新しいドメインの Module.module に挿入します。つまり、コアでは、Module.module にまだ 0 個のモジュールがあります。コンストラクターにあったものではなく、モジュールを登録する別の関数を作成することで、これを修正できました。それでも、モジュールの元のドメインのメモリにアクセスしたり、新しいドメインのメモリにアクセスしたりすることがあります。これにより、トラブルが発生します。カーネルからもモジュールからも常に同じメモリにアクセスできるようにするにはどうすればよいですか?

私がする必要があることの例は次のとおりです。

  • AppDomain A のメモリにあるクラスのインスタンスへのポインタを、AppDomain B にあるモジュールのフックに渡します。
  • モジュールにそのクラスの何かを変更させます (ドメイン B ではなく、ドメイン A のメモリ内)。
4

2 に答える 2

0

Statics はAppDomains によって共有されません! 各 AppDomain には、異なるモジュールのリストがあります。

于 2012-11-15T14:21:10.060 に答える
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;
        }
    }
}

出力

于 2012-11-26T02:13:30.923 に答える