Use the [Serializable] attribute or subclassing from MarshalByRefObject?

白昼怎懂夜的黑 提交于 2019-12-02 19:15:35

Using MarshallByRef will execute your methods in the remote AppDomain. When you use CreateInstanceAndUnwrap with a Serializable object, a copy of the object is made to the local AppDomain, so any method call will be executed in the local AppDomain.

If what you want is to communicate between AppDomains go with the MarshallByRef approach.

An example:

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());

    }
}

This code will display "OtherAppDomain" when you call WhatIsMyAppDomain from the MarshallByRef object, and your default AppDomain name when you call from the Serializable object.

These approaches have dramatically different effects.

With the MarshalByRef version you are creating 1 instance of your object. It will live in the newly created AppDomain. All accesse to the object is done via a TransparentProxy.

With the Serializable version you are created 2 instances of your object. One is created in the newly created AppDomain. The CreateInstanceAndUnwrap call will then serialize this object and deserialize it in the original app domain. This creates a second version of the object that is completely independent from the first. In fact, the very next GC will almost certainly eliminate the original object and you'll be left with one instance.

Why do both approaches have the same effect?

They do not have the same effect.

With MarshalByRefObject you are referencing one object across AppDomain boundaries. With [Serializable] a copy of the object is being made. This will show up if the state of the object is modified in the child domain and then examined again (or execute the Console.WriteLine inside the child AppDomain).

MarshalByRefValue and Serializable implement different semantics for remoting/cross AppDomain communication. MarshalByRefValue essentially gives you reference semantics through a proxy object, while Serializable gives you value semantics (i.e. the state of the object is copied).

In other words MarshalByRefValue will let you modify the instance across different AppDomains, while Serializable will not. The latter is useful when you just need to get the information from one AppDomain to another, e.g. to get the content of an exception from one AppDomain to another.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!