Question

I need to dynamically load an interface assembly that I use on client-side remoting. Something like this.

static void Main(string[] args)
{
  TcpClientChannel clientChannel = new TcpClientChannel();
  ChannelServices.RegisterChannel(clientChannel, false);

  Assembly interfaceAssembly = Assembly.LoadFile("RemotingInterface.dll");
  Type iTheInterface = 
    interfaceAssembly.GetType("RemotingInterface.ITheService");

  RemotingConfiguration.RegisterWellKnownClientType(iTheInterface,
                                        "tcp://localhost:9090/Remotable.rem");
  object wellKnownObject = Activator.GetObject(iTheInterface, 
                                        "tcp://localhost:9090/Remotable.rem");
}

Only I can't seem to grasp how to call any methods as I can't cast the Activator.GetObject. How can I create a proxy of ITheService without knowing the interface at compile-time?

Was it helpful?

Solution

Got an answer from MSDN forums.

static void Main(string[] args)
{
  TcpClientChannel clientChannel = new TcpClientChannel();
  ChannelServices.RegisterChannel(clientChannel, false);

  Assembly interfaceAssembly = Assembly.LoadFile("RemotingInterface.dll");
  Type iTheInterface = interfaceAssembly.GetType("RemotingInterface.ITheService");

  RemotingConfiguration.RegisterWellKnownClientType(iTheInterface,
                                    "tcp://localhost:9090/Remotable.rem");
  object wellKnownObject = Activator.GetObject(iTheInterface, 
                                    "tcp://localhost:9090/Remotable.rem");

  MethodInfo m = iTheInterface.GetMethod("MethodName");
  m.Invoke(wellKnownObject, new object[] { "Argument"});
}

OTHER TIPS

The returned object implements the interface, so you can use reflection to get its member methods and invoke them.

Or, in C#4, you can use dynamic:

dynamic wellKnownObject = Activator.GetObject(iTheInterface, 
    "tcp://localhost:9090/Remotable.rem");

wellKnownObject.SomeMethod(etc ..);

First, inspect the available methods/interfaces of your object:

object wellKnownObject =
  Activator.GetObject(iTheInterface, "tcp://localhost:9090/Remotable.rem");

var objType = wellKnownObject.GetType();
var methods = objType.GetMethods();
var interfaces = objType.GetInterfaces();

After you're sure about the method you want to invoke,

  1. Consider using DLR and/or wrap the dynamic object in a DynamicObject container.
  2. Use methods[i].Invoke on the object.

Here are some examples:

namespace ConsoleApplication1
{
  using System;

  class Program
  {

    static void Main()
    {
      //Using reflection:
      object obj = GetUnknownObject();
      var objType = obj.GetType();

      var knownInterface = objType.GetInterface("IA");
      var method = knownInterface.GetMethod("Print");
      method.Invoke(obj, new object[] { "Using reflection" });

      //Using DRL
      dynamic dObj = GetUnknownObject();
      dObj.Print("Using DLR");

      //Using a wrapper, so you the dirty dynamic code stays outside
      Marshal marshal = new Marshal(GetUnknownObject());
      marshal.Print("Using a wrapper");

    }

    static object GetUnknownObject()
    {
      return new A();
    }
  } //class Program

  class Marshal
  {
    readonly dynamic unknownObject;
    public Marshal(object unknownObject)
    {
      this.unknownObject = unknownObject;
    }

    public void Print(string text)
    {
      unknownObject.Print(text);
    }
  }

  #region Unknown Types
  interface IA
  {
    void Print(string text);
  }

  class A : IA
  {
    public void Print(string text)
    {
      Console.WriteLine(text);
      Console.ReadKey();
    }
  }
  #endregion Unknown Types
}

Can I get the Interface information from the remoting URL like http://localhost:8080/xxx.rem?wsdl.

As WebService, I can get the interface information from the service url, http://xXX.xx.xxx.xx/url.svc?wsdl, and compile the assembly by myself code, and invoke methods via reflection.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top