I am having issues while passing objects across Appdomains.During further investigation I found that the issue is due to the IronPython object not been Serialized. This IronPython object is derived from a .NET base class. The .NET base class is derived from MarshalByRefObj.
Let me explain my environment. I have IronPython embedded in my C# application. It is imposed that every class in IronPython inherit the .NET base class say ClassA. ClassA is derived from MarshalByRefObj as I need to pass an instance of this class to another appdomain. I create a new appdomain and pass the instance of ClassA to this Appdomain. While calling a method in python class through the instance of ClassA I get an exception mentioning that "Type 'IronPython.Runtime.Types.PythonType' in Assembly 'IronPython, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' is not marked as serializable"
How can I serialize python objects from C# or is there any other way to tackle this situation.
Update
More insight into the problem. If I instantiate the class where I access python methods in the default appdomain and then pass the instance to the created appdomain then the above mentioned issue is not seen. On the other side when I Instantiate the class where I access the python method in the created appdomain and then access the python methods then the serialization exception is thrown.
One way I see to resolve this issue is that i modify the IronPython source code to serialize the types that are required. Is there any other way that i can do to get around this issue.
Here is a sample code to reproduce the exception I encountered
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);
}
}