Передача объектов через домены приложений - PullRequest
2 голосов
/ 17 марта 2010

У меня возникают проблемы при передаче объектов через домены приложений. В ходе дальнейшего расследования я обнаружил, что проблема связана с тем, что объект 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);
    }
}

1 Ответ

2 голосов
/ 17 августа 2010

Это работает для меня сейчас.

Проблема заключалась в том, что я пытался вернуть объекты из удаленного домена в локальный домен. ObjectOperations имеет набор перегрузок, которые принимают ObjectHandles, и имеет некоторые другие методы, которые возвращают ObjectHandles для работы с объектами в удаленном домене приложения. Если приведенный выше код изменен на код ниже, он работает.

Добавить: с помощью System.Runtime.Remoting

        var subClass = scope.GetVariableHandle("C"); // get back a handle
        var instance = ops.Invoke(subClass, new ObjectHandle[0]); // invoke the handle to create an instance

        mbr = instance.Unwrap() as MbrBase; // now we know we have an MBR and we can unwrap it to our local side

P.S. Я получил решение от сообщества Iron Python.

...