Marshal by Reference is a process where an object is passed between contexts (e.g., between application domains, across processes, or from managed to unmanaged code) by reference, rather than by value. This means that the object itself is not copied but a reference (or pointer) to the object is passed. This allows the receiving context to access and modify the original object, rather than working with a copy of the object’s data.
When marshalling by reference, changes made to the object in the target context are reflected in the source context because both the source and target share the same reference to the object.
Marshalling: This is the process of converting data from one format or context to another, allowing data to be transmitted between different parts of an application or system.
Marshal by Reference: In this case, a reference (not a copy) to the object is passed across the context boundary. The target code can then access and modify the original object, not just a copy of it.
Reference Types: Most .NET objects (instances of classes) are reference types. When you pass a reference type object by reference, both the source and destination share the same memory location for the object, and changes to the object in one context affect the object in the other.
MarshalByRefObject: In .NET, objects that need to be marshaled by reference across application domains must derive from the MarshalByRefObject class. This class allows objects to be accessed remotely, across application domains, or even between processes in certain contexts (like remoting).
In the context of application domains, marshalling by reference allows an object to be used across different application domains without copying the data. Instead, a reference to the object is passed, enabling both application domains to interact with the same instance.
When an object is marshaled by reference across application domains, the CLR ensures that the object is available in both domains, but the object remains in the source domain. The target domain simply holds a reference to the original object.
using System;
public class MyClass : MarshalByRefObject
{
public int Value { get; set; }
public MyClass(int value)
{
Value = value;
}
public void DisplayValue()
{
Console.WriteLine($"Value: {Value}");
}
}
public class Program
{
public static void Main()
{
// Create a new application domain
AppDomain newAppDomain = AppDomain.CreateDomain("NewAppDomain");
// Create an instance of MyClass in the main AppDomain
MyClass myObject = new MyClass(42);
// Marshal by reference: pass a reference to the object to the new AppDomain
MyClass myObjectInNewDomain = (MyClass)newAppDomain.CreateInstanceAndUnwrap(
typeof(MyClass).Assembly.FullName, "MyClass");
// Call a method from the object in the new AppDomain
myObjectInNewDomain.DisplayValue();
// Modify the original object
myObject.Value = 100;
// Display the modified value in the main AppDomain
Console.WriteLine($"Modified Value in main AppDomain: {myObject.Value}");
// Unload the application domain
AppDomain.Unload(newAppDomain);
}
}
In this example:
MyClass is derived from MarshalByRefObject to enable marshalling by reference.MyClass in the main application domain and then pass a reference to this object to the new application domain.Value in the main domain, the change is reflected in both domains, showing that the same reference is shared.In .NET, to use marshal-by-reference, you must derive your class from the MarshalByRefObject class. This class enables objects to be passed by reference across different application domains, allowing remote access to the object.
Here’s an example of defining a class with MarshalByRefObject:
using System;
public class MyClass : MarshalByRefObject
{
public int Value { get; set; }
public MyClass(int value)
{
Value = value;
}
public void DisplayValue()
{
Console.WriteLine($"Value: {Value}");
}
}
public class Program
{
public static void Main()
{
MyClass myObject = new MyClass(10);
// Marshalling by reference
MyClass refObject = myObject; // Pass the reference
// Both 'myObject' and 'refObject' refer to the same object
refObject.Value = 20;
// Output will be:
Console.WriteLine($"myObject Value: {myObject.Value}"); // Output: 20
Console.WriteLine($"refObject Value: {refObject.Value}"); // Output: 20
}
}
refObject directly affect myObject because they both refer to the same memory location.In .NET Remoting, marshalling by reference enables the creation of remote objects that can be accessed from different application domains, machines, or processes.
Here’s an example of using remoting with Marshal by Reference:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
public class MyClass : MarshalByRefObject
{
public int Value { get; set; }
public MyClass(int value)
{
Value = value;
}
public void DisplayValue()
{
Console.WriteLine($"Value: {Value}");
}
}
public class Program
{
public static void Main()
{
// Create a channel for remoting communication
TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel, false);
// Register the remote object
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(MyClass), "MyRemoteObject", WellKnownObjectMode.SingleCall);
// Wait for remote calls
Console.WriteLine("Server is waiting for client requests...");
Console.ReadLine();
}
}
In this example:
MyClass derives from MarshalByRefObject, allowing it to be accessed remotely across different application domains or machines.RemotingConfiguration.RegisterWellKnownServiceType makes the object available for remote calls.This is an example of how objects can be accessed remotely via .NET Remoting. Changes made to the remote object will be reflected across all clients accessing that object by reference.
| Feature | Marshal by Value | Marshal by Reference |
|---|---|---|
| Object Passing | A copy of the object is passed. | A reference to the original object is passed. |
| Changes in Target | Changes do not affect the original object. | Changes are reflected in the original object. |
| Memory Consumption | Higher memory consumption (due to object copy). | Lower memory consumption (no object copy). |
| Isolation | Objects in different contexts are independent. | Objects are shared across contexts. |
| Use Case | Useful when you need to isolate data between domains. | Useful when you need to share data between domains. |
While marshalling by reference is useful in various scenarios (e.g., remote object access, cross-domain communication), there are some limitations:
MarshalByRefObject is used to create objects that are marshaled by reference across application domains or processes.Marshalling by reference is particularly useful when you need to share state or interact with the same object across different application domains or processes, without needing to duplicate the object’s data. However, it requires careful consideration of memory management and security
Open this section to load past papers