2010-03-17 16 views
2

Je rencontre des problèmes lors du passage d'objets sur Appdomains.Pendant une enquête plus approfondie, j'ai trouvé que le problème est dû à l'objet IronPython n'a pas été sérialisé. Cet objet IronPython est dérivé d'une classe de base .NET. La classe de base .NET est dérivée de MarshalByRefObj. Laissez-moi vous expliquer mon environnement.Passage d'objets à travers Appdomains

J'ai IronPython incorporé dans mon application C#. Il est imposé que chaque classe dans IronPython hérite de la classe de base .NET, disons ClassA. ClassA est dérivé de MarshalByRefObj car j'ai besoin de passer une instance de cette classe à un autre domaine d'application. Je crée un nouveau domaine d'application et transmets l'instance de ClassA à ce domaine. Lors de l'appel d'une méthode en classe python via l'instance de ClassA, j'obtiens une exception mentionnant que "Type" IronPython.Runtime.Types.PythonType 'dans Assembly' IronPython, Version = 2.0.0.0, Culture = Neutre, PublicKeyToken = 31bf3856ad364e35 'n'est pas marqué comme sérialisable "

Comment puis-je sérialiser des objets Python à partir de C# ou existe-t-il un autre moyen de résoudre cette situation?

Mise à jour

Plus aperçu du problème. Si j'instancie la classe dans laquelle j'accède aux méthodes python dans le domaine d'application par défaut, puis que je passe l'instance au domaine d'application créé, le problème mentionné ci-dessus n'est pas visible. De l'autre côté, lorsque j'instancie la classe dans laquelle j'accède à la méthode python dans le domaine d'application créé, puis j'accède aux méthodes python, l'exception de sérialisation est lancée. Un moyen que je vois pour résoudre ce problème est que je modifie le code source IronPython pour sérialiser les types qui sont requis. Y a-t-il un autre moyen de contourner ce problème?

Voici un exemple de code pour reproduire l'exception que je rencontrais

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); 
    } 
} 
+0

@Mustaq Si vous avez des informations supplémentaires à fournir concernant votre problème, veuillez le faire en éditant votre question originale et en ajoutant cette information. Le poseur de questions ne devrait généralement pas poster quoi que ce soit en dessous de cette question, c'est là que les réponses vont. – Sampson

Répondre

2

Cela fonctionne pour moi maintenant.

Le problème était que j'essayais de renvoyer les objets du domaine distant dans le domaine local. ObjectOperations a un ensemble de surcharges qui prennent ObjectHandles et d'autres méthodes qui retournent ObjectHandles pour travailler avec des objets dans un domaine d'application distant. Si le code ci-dessus est modifié pour le code ci-dessous cela fonctionne.

Ajouter: en utilisant 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 

post-scriptum J'ai obtenu la solution de la communauté Iron Python.