Use the [Serializable] attribute or subclassing from MarshalByRefObject?

不打扰是莪最后的温柔 提交于 2019-12-20 09:37:17

问题


I'd like to use an object across AppDomains.

For this I can use the [Serializeable] attribute:

[Serializable]
class MyClass
{
    public string GetSomeString() { return "someString" }
}

Or subclass from MarshalByRefObject:

class MyClass: MarshalByRefObject
{
    public string GetSomeString() { return "someString" }
}

In both cases I can use the class like this:

AppDomain appDomain = AppDomain.CreateDomain("AppDomain");
MyClass myObject = (MyClass)appDomain.CreateInstanceAndUnwrap(
                   typeof(MyClass).Assembly.FullName,
                   typeof(MyClass).FullName);
Console.WriteLine(myObject.GetSomeString());

Why do both approaches seem to have the same effect? What is the difference in both approaches? When should I favor the one approach over the other?

EDIT: At the surface I know that there are differences between both mechanisms, but if someone jumped out of a bush and asked me the question I couldn't give him a proper answer. The questions are quite open questions. I hoped that someone can explain it better than I could do.


回答1:


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.




回答2:


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.




回答3:


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).




回答4:


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.



来源:https://stackoverflow.com/questions/599731/use-the-serializable-attribute-or-subclassing-from-marshalbyrefobject

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