Shhh... Don't Tell Anyone but I am using .NET Remoting: Part 1 - Use CLR Interfaces

One of the easiest ways to avoid locking yourself into .NET Remoting is to avoid exposing its most infamous type in your contract:  MarshalByRefObject (MBRO).  To marshal object references in .NET Remoting your type needs to inherit from MBRO but that doesn't mean your contract needs to expose types that inherit from MBRO.

Use CLR Interfaces for the remote objects in your contract.  

This isn't really new advice.  Ingo Rammer has suggested this in his book as well.  Interestingly, those of you following the Indigo programming model will have seen a lot of interface usage so this pattern will carry forward nicely. 

Let's take an example:

Server code:
public class HelloObject : MarshalByRefObject, IHello
{
   string IHello.HelloWorld(string name)
   {
      return "Hello, " + name;
   }
}

Shared code:
public interface IHello
{
   string HelloWorld(string name);
}

Now you can register HelloObject on the server side but get an instance of the remote object with the following call:

IHello proxy = (IHello)Activator.GetObject(typeof(IHello), "tcp://localhost/Hello.rem");

There are some major advantages to this approach:

- Only the interface needs to be shared, which allows for greater flexibility in versioning and deployment
- The interface (and hence contract) that has been established can be re-used later as part of the migration to Indigo

There is one disadvantage to this approach:

- Interception of new() is not supported

I will talk about how to get this support back in a future section of this series.

Q&A and updates---

Here are some good questions I got on this post with some of my answers...

Q: Why by exposing a type that inherits from MarshalByRefObject I'll get locked into Remoting? What you said in your post is a good code practice but not necessary.

A:  .NET Remoting requires the sharing of types between client and server.  Imagine that a new programming model came along that used a new infrastructure class for intercepting object creation and proxy generation (MBRO2). Keeping your interface seperate from your implementation allows you switch from MBRO to MBRO2 without changing the contract with the server or the type that you program against (i.e., the interface).  You might have to change activation code but the programming experience against the remoted object can remain constant.  Like you say, it isn't required but it is a good practice. 

Q: MBRO belongs to System namespace and not Remoting, any time you cross app domain boundaries to call your object you need it's ObjRef so it is not remoting specific to inherit from MBRO.

A:  Crossing AppDomain boundaries within a process using MBRO *is* .NET Remoting.  It isn't the same exact programming model for activation but it is using the .NET Remoting infrastructure.