Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use the [Serializable] attribute or subclassing from MarshalByRefObject?

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.

like image 426
Theo Lenndorff Avatar asked Mar 01 '09 12:03

Theo Lenndorff


People also ask

What is the use of serializable attribute in C#?

Serialization is the process of converting an object into a stream of bytes to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed. The reverse process is called deserialization.

Can serializable class inherited?

You must explicitly mark each derived class as [Serializable] . If, however, you mean the ISerializable interface, then yes: interface implementations are inherited, but you need to be careful - for example by using a virtual method so that derived classes can contribute their data to the serialization.


2 Answers

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.

like image 96
Jorge Villuendas Zapatero Avatar answered Oct 02 '22 11:10

Jorge Villuendas Zapatero


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.

like image 28
JaredPar Avatar answered Oct 02 '22 11:10

JaredPar