.NET Remoting with Reflection
-
14-11-2019 - |
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?
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,
- Consider using DLR and/or wrap the dynamic object in a DynamicObject container.
- 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.