Поведение DoCallBack CrossAppDomainDelegate для нестатических делегатов

Пожалуйста, рассмотрите следующий фрагмент кода:

// Create a new application domain
AppDomain ad = AppDomain.CreateDomain("New domain");

Worker work = new Worker();

// if Worker class is marked as 'MarshalByRefObject', this will run in current
// appdomain.
// if Worker class is NOT marked as 'MarshalByRefObject' and is marked as
// 'Serializable', this will run in a new appdomain.
ad.DoCallBack(work.PrintDomain);
// or ad.DoCallBack(new CrossAppDomainDelegate(work.PrintDomain));

// But for static methods:
// If ppp method is static, no marking is required and it will run in
// a new AppDomain.
ad.DoCallBack(Worker.ppp);

Как мы можем объяснить это поведение DoCallBack?

  1. Почему нестатический метод PrintDomain выполняется в текущем домене, когда Worker класс помечен MarshalByRefObject?
  2. Почему нестатический метод PrintDomain выполняется в новом AppDomain, когда Worker класс помечен Serializable?
  3. Почему статический метод не нуждается в маркировке?

1 ответ

Решение

Почему нестатический метод PrintDomain выполняется в текущем домене, когда класс Worker помечен как MarshalByRefObject?

Поскольку это то, что делает MBRO, он создает прокси для объекта, созданного в основном домене приложения. Который выполняет маршализацию вызова от вторичного домена приложения к домену приложения, которому принадлежит объект, первичный домен приложения.

Почему нестатический метод PrintDomain выполняется в новом AppDomain, когда класс Worker помечен как Serializable?

Потому что этот сценарий не использует прокси. Сам объект маршалируется с первичного на вторичный домен приложения. Возможно, потому что вы отметили его [Сериализуемый]. Следовательно, вызов выполняется во вторичном домене приложения.

Почему статический метод не нуждается в маркировке?

Непонятно, что вы подразумеваете под "маркировкой", но для статического метода это не отличается. Некоторый код для игры, удалите комментарий к базовому классу, чтобы сравнить два сценария:

using System;

class Program {
    static void Main(string[] args) {
        var dom = AppDomain.CreateDomain("Test");
        var obj = new WorkerMbro();
        dom.DoCallBack(obj.PrintDomain);
        dom.DoCallBack(obj.PrintDomainStatic);
        Console.ReadLine();
    }
}
[Serializable]
class WorkerMbro /* : MarshalByRefObject */ {
    public void PrintDomain() {
        Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
    }
    public void PrintDomainStatic() {
        Console.WriteLine(AppDomain.CurrentDomain.FriendlyName);
    }
}

Вывод как опубликовано:

Test
Test

Вывод с удаленными комментариями, поэтому используется прокси:

ConsoleApplication1.vshost.exe
ConsoleApplication1.vshost.exe
Другие вопросы по тегам