C# 带反射的.NET远程处理
我需要动态加载在客户端远程处理上使用的接口程序集。像这样的C# 带反射的.NET远程处理,c#,.net,reflection,.net-remoting,activator,C#,.net,Reflection,.net Remoting,Activator,我需要动态加载在客户端远程处理上使用的接口程序集。像这样的 static void Main(string[] args) { TcpClientChannel clientChannel = new TcpClientChannel(); ChannelServices.RegisterChannel(clientChannel, false); Assembly interfaceAssembly = Assembly.LoadFile("RemotingInterface.d
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");
}
只是我似乎无法掌握如何调用任何方法,因为我无法强制转换Activator.GetObject。如何在编译时不知道接口的情况下创建ITheService的代理?返回的对象实现接口,因此您可以使用反射获取其成员方法并调用它们 或者,在C#4中,您可以使用
dynamic
:
dynamic wellKnownObject = Activator.GetObject(iTheInterface,
"tcp://localhost:9090/Remotable.rem");
wellKnownObject.SomeMethod(etc ..);
首先,检查对象的可用方法/接口:
object wellKnownObject =
Activator.GetObject(iTheInterface, "tcp://localhost:9090/Remotable.rem");
var objType = wellKnownObject.GetType();
var methods = objType.GetMethods();
var interfaces = objType.GetInterfaces();
确定要调用的方法后
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
}
我从他那里得到了答案
我可以从远程URL获取接口信息吗
作为WebService,我可以从服务url获取接口信息,自己编写程序集代码,并通过反射调用方法。Hi Ben。谢谢你的回复。动态方法调用抛出RuntimeBinderException“System.MarshallByRefObject”不包含“SomeMethod”的定义。此外,我知道如何获取接口的方法,但不知道如何从wellKnownObject获取它们。
SomeMethod
是一个方法的示例名称。将其替换为您知道的界面中的方法。您能展示一个反射的示例吗?对象的类型为MarshalByRefObject。我不太确定如何将其映射到界面。@Shimmy,谢谢您的更新。不幸的是,你的例子都不起作用。请记住,我正在使用动态程序集加载和.NET远程处理。我甚至不知道服务器正在实例化的具体类,因此无法调用newa()
。我必须使用Activator.GetObject
,但是我得到的对象类型是MarshalByRefObject
,它没有实现任何接口。如果调用objType.GetInterfaces
,则返回一个空数组。如果我以传统方式执行此操作并静态引用DLL,那么我可以调用IA knownInterface=(IA)Activator.GetObject(…)
@Rubio,1)在我的示例中,新的A()
是您的Activator.GetObject
,它是,共同点是,只有在运行时将变量类型设置为具体值时,才知道变量类型2)如何确保要查找的方法存在于该远程类中?3) 让我问你一个问题,你是用反射还是?@Shimmy,我明白了。2) 我不能。3) 是的。在我的示例代码knownInterface
中,如果我像您那样获得它,它将为空。然而,如果我像在我的原始样本中那样得到它,它就会工作。所以从技术上讲,你的反射方法是正确的,我只是需要以不同的方式来获得界面。我仍然无法让DLR或包装器方法工作。我明白了。那很有趣。非常感谢。顺便说一句,如果您自己的答案回答了这个问题,请将其标记为答案。您是否考虑过使用WCF而不是远程处理?为了支持WCF,远程处理已被弃用。@John,我痛苦地意识到远程处理已被弃用。不幸的是,由于现有的客户端代码,我无法切换到WCF而不会对其他人的代码造成破坏。有一天…这篇文章是关于.NET远程处理的。如果你正在处理web服务,请使用Google“dynamic WCF”。如果你要将程序集加载到当前AppDomain中,并且你知道类型名,为什么不添加RemotingInterface.dll
作为对项目的引用,这样你就可以像ITheInterface WellKnownoObject=(ITheInterface)Activator.GetObject(…)那样强制转换代码>,然后直接执行该方法?如果您希望对动态加载的程序集进行沙箱处理,那么这并不能做到这一点。
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"});
}