How to use a variable as a method name using dynamic objects

后端 未结 4 803
迷失自我
迷失自我 2021-01-02 16:16

In SignalR there is public property defined in the HubConnectionContext as such:

public dynamic All { get; set; }

This enables users to cal

相关标签:
4条回答
  • 2021-01-02 16:52
    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();
    }
    
    0 讨论(0)
  • 2021-01-02 17:12

    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);
    }
    
    0 讨论(0)
  • 2021-01-02 17:17

    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);
    }
    
    0 讨论(0)
  • 2021-01-02 17:19

    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);
    
    0 讨论(0)
提交回复
热议问题