The*_*rff 17 c# remoting appdomain
我想在AppDomains中使用一个对象.
为此,我可以使用[Serializeable]属性:
[Serializable]
class MyClass
{
public string GetSomeString() { return "someString" }
}
Run Code Online (Sandbox Code Playgroud)
或MarshalByRefObject的子类:
class MyClass: MarshalByRefObject
{
public string GetSomeString() { return "someString" }
}
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,我都可以使用这样的类:
AppDomain appDomain = AppDomain.CreateDomain("AppDomain");
MyClass myObject = (MyClass)appDomain.CreateInstanceAndUnwrap(
typeof(MyClass).Assembly.FullName,
typeof(MyClass).FullName);
Console.WriteLine(myObject.GetSomeString());
Run Code Online (Sandbox Code Playgroud)
为什么两种方法似乎都有相同的效果?两种方法有什么不同?我什么时候应该支持另一种方法呢?
编辑:从表面上看,我知道两种机制之间存在差异,但如果有人跳出丛林并问我这个问题,我无法给他一个正确的答案.问题是非常开放的问题.我希望有人可以比我能做的更好地解释它.
Jor*_*ero 21
使用MarshallByRef将在远程AppDomain中执行您的方法.当您将CreateInstanceAndUnwrap与Serializable对象一起使用时,该对象的副本将发送到本地AppDomain,因此任何方法调用都将在本地AppDomain中执行.
如果您想要的是在AppDomains之间进行通信,请使用MarshallByRef方法.
一个例子:
using System;
using System.Reflection;
[Serializable]
public class SerializableClass
{
public string WhatIsMyAppDomain()
{
return AppDomain.CurrentDomain.FriendlyName;
}
}
public class MarshallByRefClass : MarshalByRefObject
{
public string WhatIsMyAppDomain()
{
return AppDomain.CurrentDomain.FriendlyName;
}
}
class Test
{
static void Main(string[] args)
{
AppDomain ad = AppDomain.CreateDomain("OtherAppDomain");
MarshallByRefClass marshall = (MarshallByRefClass)ad.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, "MarshallByRefClass");
SerializableClass serializable = (SerializableClass)ad.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, "SerializableClass");
Console.WriteLine(marshall.WhatIsMyAppDomain());
Console.WriteLine(serializable.WhatIsMyAppDomain());
}
}
Run Code Online (Sandbox Code Playgroud)
当您从MarshallByRef对象调用WhatIsMyAppDomain时,此代码将显示"OtherAppDomain",当您从Serializable对象调用时,此代码将显示默认的AppDomain名称.
Jar*_*Par 10
这些方法具有截然不同的效果.
使用MarshalByRef版本,您将创建一个对象实例.它将存在于新创建的AppDomain中.对象的所有访问都是通过TransparentProxy完成的.
使用Serializable版本,您将创建2个对象实例.一个是在新创建的AppDomain中创建的.然后,CreateInstanceAndUnwrap调用将序列化此对象并在原始应用程序域中对其进行反序列化.这将创建与第一个版本完全独立的对象的第二个版本.事实上,下一个GC几乎肯定会消除原始对象,你将留下一个实例.
为什么两种方法都有相同的效果?
它们没有相同的效果.
随着MarshalByRefObject
您在AppDomain边界引用一个对象.随着[Serializable]
对象的副本正在取得进展.这将显示是否在子域中修改了对象的状态,然后再次检查(或执行Console.WriteLine
子AppDomain内部).