Directory Freebies VS CheatSheet Forum

RSS

Email

Translate

Home About Archive Privacy Contact Advertise Guest Post
Posted by Shahar A on May 22nd, 2008 | Filed under .Net, C#, Misc. |

The ServiceContainer, implementing the IServiceContainer Interface is used to store and retrieve services. it is used for Dependency Injection, a very important concept that allows separating independent components, and is widely discussed over the web. However, one drawback of this implementation is it does not work with .net  remoting… When you try to add a remote proxy object to the container you’ll get the following exception: “The service instance must derive from or implement XXX“. Follow this simple example of a remote calculator client (I’ll add the server code at the end) and than we’ll understand what’s wrong using our friend - the reflector:

TcpChannel channel = new TcpChannel();
ChannelServices.RegisterChannel(channel);
ICalculator calculator =(ICalculator)Activator.GetObject(
        typeof(ICalculator),"tcp://localhost:1235/RemoteCalculator");

IServiceContainer serviceContainer = new ServiceContainer();
serviceContainer.AddService(typeof(ICalculator), calculator);

Now open reflector and locate the AddService implementation - see the type check code:

...
if ((!(serviceInstance is ServiceCreatorCallback) &&
    !serviceInstance.GetType().IsCOMObject) &&
    !serviceType.IsAssignableFrom(serviceInstance.GetType()))
{
    throw new ArgumentException(SR.GetString("ErrorInvalidServiceInstance",
                                  new object[]  { serviceType.FullName }));
}
...

But, the calculator object is actually a proxy to a calculator, which does not implement the interface by himself and this is why the exception is thrown. The missing line here should be:

&& !serviceInstance.GetType().IsMarshalByRef

So, if you do want to use ServiceContainer with Remoting, a possible solution would be to inherit from it and implement the virtual method AddService yourself, adding the missing line.

Here is the server code I used:

public interface ICalculator
{
    int Add(int a, int b);
}
...
class Calculator : MarshalByRefObject, ICalculator
{
    int ICalculator.Add(int a, int b)
    {
        Console.WriteLine(string.Format("ICalculator.Add({0}, {1})", a, b));
        return a + b;
    }
}
...
TcpChannel channel = new TcpChannel(1235);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(
    typeof(Calculator), "RemoteCalculator", WellKnownObjectMode.Singleton);
Tags: , , , , , , , ,

Post a Comment

Advertise on Dev102 Bitrix Site Manager

Read reviews and compare prices on : Laptops , Software Like Windows, Office Suites & Many More.

Advertise on Dev102
Write Article for Dev102

Write for us!

We pay for user submitted tutorials and articles that we publish. Anyone can send in a contribution

Learn More