In SignalR there is public property defined in the HubConnectionContext as such:
public dynamic All { get; set; }
This enables users to cal
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();
}
While I love all the fun reflection answers, there's a much simpler and faster way to invoke client hub methods using a string as the method Name.
Clients.All
, Clients.Others
, Clients.Caller
, Clients.AllExcept(connectionIds)
, Clients.Group(groupName)
, Clients.OthersInGrouop(groupName)
, and Clients.Client(connectionId)
are all dynamic objects, but they also all implement the IClientProxy interface.
You can cast any of these dynamic objects to an IClientProxy
, and then call Invoke(methodName, args...):
public void AcceptSignal(string methodToCall, string msg)
{
IClientProxy proxy = Clients.All;
proxy.Invoke(methodToCall, msg);
}
You can use reflection to achieve this:
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);
}
You can use reflection to find the method. But this will only work if it is a "real" non-dynamic method which is defined in the usual non-dynamic way, only hidden behind the dynamic
keyword.
If however the object All
is truely dynamic, like an ExpandoObject
or something else deriving from System.Dynamic.DynamicObject
, the "method" could be something that was only associated with the type at runtime, and in that case typeof(All).GetMethod
won't find anything.
It was Ilya Ivanov who originally pointed this out, in a comment to John Willemse's answer. It became apparent that the object is a Microsoft.AspNet.SignalR.Hubs.ClientProxy instance.
Therefore, from the documentation of that type, the solution is:
string methodToCall = XXX;
string msg = YYY;
((ClientProxy)(Clients.All)).Invoke(methodToCall, msg);