gpt4 book ai didi

c# - 跨 Appdomains 传递对象

转载 作者:太空宇宙 更新时间:2023-11-03 11:49:30 25 4
gpt4 key购买 nike

我在跨 Appdomains 传递对象时遇到问题。在进一步调查过程中,我发现问题是由于 IronPython 对象未被序列化。此 IronPython 对象派生自 .NET 基类。 .NET 基类派生自 MarshalByRefObj。

让我解释一下我的环境。我的 C# 应用程序中嵌入了 IronPython。 IronPython 中的每个类都强制继承 .NET 基类,例如 ClassA。 ClassA 派生自 MarshalByRefObj,因为我需要将此类的实例传递给另一个应用程序域。我创建了一个新的应用程序域并将 ClassA 的实例传递给这个应用程序域。通过 ClassA 的实例调用 python 类中的方法时,我得到一个异常,提到“在程序集‘IronPython,Version=2.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35’中输入‘IronPython.Runtime.Types.PythonType’不是标记为可序列化”

我如何从 C# 中序列化 python 对象,或者是否有任何其他方法来解决这种情况。

更新

更深入地了解问题。如果我实例化我在默认应用程序域中访问 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);
}
}

最佳答案

现在这对我有用。

问题是我试图将对象从远程域返回到本地域。 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

附言我从 Iron Python 社区获得了解决方案。

关于c# - 跨 Appdomains 传递对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2459759/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com