Существует возможность обмена данными между доменами приложений без затрат на Marshalling. Но это довольно хакерский способ. Вы можете создать исходный объект данных, который по ссылке будет использоваться всеми доменами приложений. Таким образом, вы получаете все данные в один общий объект без затрат на Marshalling. Звучит слишком легко, чтобы быть правдой?
Первое, что нужно знать, это как делиться данными между доменами приложений без Marshalling. Для этого вы получите адрес объекта вашего источника данных через Marshal.UnsafeAddrOfPinnedArrayElement. Затем вы передаете этот IntPtr всем доменам приложений, которые заинтересованы в этом. В целевом AppDomain вам необходимо преобразовать этот IntPtr обратно в ссылку на объект, что можно сделать JIT :: CastAny, что делается, если вы возвращаете объект из метода и помещаете его указатель в стек.
Виола, вы разделили объект как простой указатель между доменами приложений и получили InvalidCastExceptions. Проблема заключается в том, что вы должны установить для всех ваших доменов приложений LoaderOptimization.MultiDomain, чтобы гарантировать, что сборка, определяющая общий тип данных, загружается как нейтральный тип AppDomain, имеющий одинаковый указатель таблицы методов между всеми доменами приложений.
Вы можете найти пример приложения, которое делает именно это как часть WMemoryProfiler. См. Эту ссылку для получения более подробного объяснения и ссылки для загрузки с примером кода.
Основной код
[LoaderOptimization(LoaderOptimization.MultiDomain)]
static public void Main(string[] args)
{
// To load our assembly appdomain neutral we need to use MultiDomain on our hosting and child domain
// If not we would get different Method tables for the same types which would result in InvalidCastExceptions
// for the same type.
var other = AppDomain.CreateDomain("Test"+i.ToString(), AppDomain.CurrentDomain.Evidence, new AppDomainSetup
{
LoaderOptimization = LoaderOptimization.MultiDomain,
});
// Create gate object in other appdomain
DomainGate gate = (DomainGate)other.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(DomainGate).FullName);
// now lets create some data
CrossDomainData data = new CrossDomainData();
data.Input = Enumerable.Range(0, 10).ToList();
// process it in other AppDomain
DomainGate.Send(gate, data);
// Display result calculated in other AppDomain
Console.WriteLine("Calculation in other AppDomain got: {0}", data.Aggregate);
}
}