Поведение 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
?
- Почему нестатический метод
PrintDomain
выполняется в текущем домене, когдаWorker
класс помеченMarshalByRefObject
? - Почему нестатический метод
PrintDomain
выполняется в новом AppDomain, когдаWorker
класс помеченSerializable
? - Почему статический метод не нуждается в маркировке?
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