如何使用动态对象将变量用作方法名称
在SignalR中,HubConnectionContext中定义了公共属性,如下所示:
public dynamic All { get; set; }
这使用户可以像下面这样调用它: All.someMethodName();
这很棒。
我现在想在我的函数中使用传入参数来调用它。 我怎样才能做到这一点?
如: All.();
有没有办法做到这一点?
谢谢
编辑示例:
public void AcceptSignal(string methodToCall, string msg) { Clients.All.someMethod(msg); // THIS WORKS Clients.All.(msg); // THIS DOES NOT WORK (But I would like it to!) }
虽然我喜欢所有有趣的reflection答案,但是使用字符串作为方法名称来调用客户端集线器方法的方法要简单得多。
Clients.All
, Clients.Others
, Clients.Caller
, Clients.AllExcept(connectionIds)
, Clients.Group(groupName)
, Clients.OthersInGrouop(groupName)
和Clients.Client(connectionId)
都是动态对象,但它们都是实现的IClientProxy接口。
您可以将任何这些动态对象IClientProxy
转换为IClientProxy
,然后调用Invoke(methodName,args …) :
public void AcceptSignal(string methodToCall, string msg) { IClientProxy proxy = Clients.All; proxy.Invoke(methodToCall, msg); }
您可以使用reflection来实现此目的:
Type allType = All.GetType(); // GetType() may return null in relation to dynamics objects if (allType != null) { MethodInfo methodInfo = allType.GetMethod(methodToCall); methodInfo.Invoke(All, null); }
public void AcceptSignal(String methodToCall, String msg) { var count=( from target in new[] { Clients.All } from memberInfo in ((Type)target.GetType()).GetMember(methodToCall) where MemberTypes.Method==memberInfo.MemberType let methodInfo=memberInfo as MethodInfo let paraInfos=methodInfo.GetParameters() where null!=paraInfos.FirstOrDefault(x => msg.GetType()==x.ParameterType) select methodInfo.Invoke(target, new object[] { msg }) ).Count(); }
您可以使用reflection来查找方法。 但这只有在它是一个“真正的”非动态方法时才有效,它以通常的非动态方式定义,只隐藏在dynamic
关键字后面。
但是,如果对象All
是真正动态的,比如ExpandoObject
或从System.Dynamic.DynamicObject
派生的其他东西,那么“method”可能只是在运行时与类型相关联的东西,在这种情况下typeof(All).GetMethod
什么都找不到。
在对John Willemse的回答发表评论时,Ilya Ivanov最初指出了这一点。 很明显,该对象是Microsoft.AspNet.SignalR.Hubs.ClientProxy
实例。
因此,从该类型的文档中,解决方案是:
string methodToCall = XXX; string msg = YYY; ((ClientProxy)(Clients.All)).Invoke(methodToCall, msg);