Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Remoting, why isn't a list remotable?

I'm using RemotingServices.Marshal and Activator.GetObject to establish a remoting channel between two simple programs residing on the same computer.

public class IpcInterface : MarshalByRefObject
{
    public int number = -1;
    public string text = "default";
    public List<String> strings;
}
// A simplification

I've confirmed that the channel exists and communication is possible, because both programs are successfully changing number and text to completely unique values (confirmed).

So I immediately tried doing the same for strings.

On one program, I called strings.Add("1"). I tried reading the contents of strings on the second program. It was empty. What's more, the count was 0. I have no idea why strings continues to have 0 objects, as if I never added them. The same thing happens for a Stack<T> and Dictionary<T, K>, I just can't add any elements to it. Just to be sure there wasn't something weird going on with reference types in general, I also tried putting a StringBuilder in the IPC interface class, and that 'state' was successfully maintained across both programs changing its value.

Question: Why isn't the list of strings being added to, and what's the solution?

I'm hoping someone with experience can spot this problem right away. I tried Googling for similar questions, but I didn't get any useful results. Surprisingly, I only got 1 good link for googling "debugging .net remoting transparent proxy". That's a second question I have, too. How can I debug the transparent proxy object?

  1. All objects are instantiated properly (there is no NullReferenceException; in fact, there are no exceptions).
like image 229
Jason Avatar asked Nov 21 '12 04:11

Jason


1 Answers

The problem is that List<T> is not in itself a MarshalByRefObject, rather, it is a serializable class. When you call the Add() method on your list, what you're actually doing is asking the remote object to serialise its list, deserialise it locally and then call the method on the local object. Your changes will never be propagated back to the remote instance of the list object.

You will have to provide methods in your IpcInterface class to manipulate the list; because this type inherits from MarshalByRefObject, the methods will be called on the remote object instead of a locally-deserialised instance.

i.e.

public class IpcInterface : MarshalByRefObject {
    public List<String> strings;

    public void Add(string value) {
        strings.Add(value);
    }
}

You may also want to expose strings as a read-only collection, otherwise you're giving the impression that it can be manipulated directly (which it cannot).

like image 187
Bradley Smith Avatar answered Nov 15 '22 13:11

Bradley Smith