У меня возникают проблемы при передаче объектов через домены приложений. В ходе дальнейшего расследования я обнаружил, что проблема связана с тем, что объект IronPython не был сериализован. Этот объект IronPython является производным от базового класса .NET. Базовый класс .NET является производным от MarshalByRefObj.
Позвольте мне объяснить мое окружение. У меня есть IronPython, встроенный в мое приложение C #. Предполагается, что каждый класс в IronPython наследует базовый класс .NET, скажем, ClassA. ClassA является производным от MarshalByRefObj, так как мне нужно передать экземпляр этого класса в другой домен приложения. Я создаю новый домен приложения и передаю экземпляр ClassA этому домену приложения. При вызове метода в классе Python через экземпляр ClassA я получаю исключение, в котором говорится, что «Type» IronPython.Runtime.Types.PythonType »в Assembly« IronPython, версия = 2.0.0.0, Culture = нейтральный, PublicKeyToken = 31bf3856ad364e35 »не помечен как сериализуемый "
Как я могу сериализовать объекты Python из C # или есть какой-то другой способ справиться с этой ситуацией.
Обновление
Более глубокое понимание проблемы. Если я создаю экземпляр класса, где я получаю доступ к методам python в домене приложения по умолчанию, а затем передаю экземпляр созданному домену приложения, то вышеупомянутая проблема не видна. С другой стороны, когда я создаю экземпляр класса, в котором я получаю доступ к методу python в созданном домене приложения, а затем обращаюсь к методам python, возникает исключение сериализации.
Один из способов решения этой проблемы - изменить исходный код IronPython, чтобы сериализовать требуемые типы. Есть ли другой способ обойти эту проблему?
Вот пример кода для воспроизведения исключения, с которым я столкнулся
using System;
using Microsoft.Scripting;
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
class Foo
{
public static void Main(string[] args)
{
AppDomain ad = AppDomain.CreateDomain("foo");
var engine = Python.CreateEngine(ad);
engine.Runtime.LoadAssembly(typeof(MbrBase).Assembly);
var code = engine.CreateScriptSourceFromString(@"
import MbrBase
class C(MbrBase):
pass
a = C()
", SourceCodeKind.Statements);
var scope = engine.CreateScope();
code.Execute(scope);
Console.WriteLine("Trying to do it... {0}",
AppDomain.CurrentDomain.Id);
MbrBase mbr = (MbrBase)scope.GetVariable("a");
string isSubClassCode = String.Format("issubclass({0},{1})", "C",
"MbrBase");
ScriptSource script =
engine.CreateScriptSourceFromString(isSubClassCode,
SourceCodeKind.Expression);
bool result = (bool)script.Execute(scope);
if (result == true)
{
ObjectOperations ops = engine.Operations;
object subClass = scope.GetVariable("C");
object instance = ops.Call(subClass);
mbr = instance as MbrBase;
}
mbr.DoItVirtually();
mbr.DoIt();
Console.ReadKey();
}
}
public class MbrBase : MarshalByRefObject
{
public virtual void DoItVirtually()
{
Console.WriteLine("Did it virtually {0}", AppDomain.CurrentDomain.Id);
}
public void DoIt()
{
Console.WriteLine("Did it {0}", AppDomain.CurrentDomain.Id);
}
}