• <七>调用服务路由改成由客户端传入


    上一节中,我们在服务端的执行方法中定死了反射的路由,如下图。

    但是实际上这个路由应该由客户端传过来,参数应该放到参数r里面去。

    上一节我们把GrpcRequest的参数类型定死了string,为了支持多参数,那么我们改一下,把参数类型改成一个字典。

     1、修改proto文件的GrpcRequest参数改成字典以支持多参数

    message GrpcRequest{
         map<string,string> requestMsg=1;
     } 

    2、修改一下GetInvokeMethod 方法的代码,base命名空间下新增一个类 ServicesRoute 保存固定字段

     public class ServicesRoute
        {
            public  const string NAMESPACE = "NameSpace";
            public  const string CLASSNAME = "ClassName";
            public  const string METHODNAME = "MethodName";
        }
        public class BuildServices
        {
            /// <summary>
            /// 执行服务
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="r"></param>
            /// <returns></returns>
            public static T GetInvokeMethod<T>(GrpcRequest r)
            {
                try
                {
                    if (r.RequestMsg == null || r.RequestMsg.Count <= 0)
                    {
                        throw (new Exception("参数无效!"));
                    }
                    string nameSpace = "", className = "", methodName = "";
                    List<Type> paratypes = new List<Type>();
                    List<string> param = new List<string>();
                    foreach (string key in r.RequestMsg.Keys)
                    {
                        switch (key)
                        {
                            case ServicesRoute.NAMESPACE:
                                nameSpace = r.RequestMsg[key];//"AidenGRPC.Module";
                                break;
                            case ServicesRoute.CLASSNAME:
                                className = r.RequestMsg[key];// "SayHelleServer";
                                break;
                            case ServicesRoute.METHODNAME:
                                methodName = r.RequestMsg[key];//"AidenGRPC.Module";
                                break;
                            default:  paratypes.Add(r.RequestMsg[key].GetType());
                                      param.Add(r.RequestMsg[key]);
                                break;
                        }                               
                    }
                    if (string.IsNullOrEmpty(nameSpace) || string.IsNullOrEmpty(className) || string.IsNullOrEmpty(methodName))
                    {
                        throw (new Exception("参数无效!"));
                    }//命名空间.类名,程序集               
                    object instance = Assembly.Load(nameSpace).CreateInstance(nameSpace + "." + className);
                    Type type = instance.GetType();
                    //根据类型创建实例
                    object obj = Activator.CreateInstance(type, true);
                    //加载方法参数类型及方法
                    MethodInfo method = null;
                    if (paratypes.Count >= 1)
                    {
                        method = type.GetMethod(methodName, paratypes.ToArray()); //加载有参方法
                        return (T)method.Invoke(obj, param.ToArray());
                    }
                    else
                    {
                        method = type.GetMethod(methodName);
                        return (T)method.Invoke(obj,null);
                    }
                    //类型转换并返回
                    
                }
                catch (Exception ex)
                {
                    //发生异常时,返回类型的默认值。
                    return default(T);
                }
            }
        }

    3、新增一个Invoke公共方法来处理服务的调用

    public  class Request
        {
            public string Ip { get; set; }
            public int Port { get; set; }
            public string ChannelRoute { get; set; }
            public Request(string ip, int port)
            {
                Ip = ip;
                Port = port;
                ChannelRoute = $"{ip}:{port}";
            }
            public GrpcResponse Invork(Dictionary<string,string> requestMsg)
            {
                Channel channel = new Channel(ChannelRoute, ChannelCredentials.Insecure);
                var client = new AidenGRPC.RPCBase.TestServer.TestServerClient(channel);
                GrpcRequest re = new GrpcRequest();
                re.RequestMsg.Add(requestMsg);
                GrpcResponse rp = client.Invoke(re);
                return rp;
            }
        }

    4、修改一下客户端的main函数

     static void Main(string[] args)
            {
                Dictionary<string, string> requestMsg = new Dictionary<string, string>();
                requestMsg.Add(ServicesRoute.NameSpace.ToString(), "AidenGRPC.Module");
                requestMsg.Add(ServicesRoute.ClassName.ToString(), "SayHelleServer");
                requestMsg.Add(ServicesRoute.MethodName.ToString(), "SayHello");
                requestMsg.Add("name","Aiden");
                GrpcResponse rp =new Request("127.0.0.1", 30052).Invoke(requestMsg);
                Console.WriteLine(rp.ResponseMsg);
                Console.WriteLine("Press any key to exit client...");
                Console.ReadKey();        
            }

    5、运行结果,如下图,已经成功了。

    
    
  • 相关阅读:
    viso图插入Word中大片空白解决办法
    面向对象设计模式中的单例模式和工厂模式
    面向对象知识整理
    require和include的区别及自动加载的定义
    面向对象的三大特性及定义
    重写和重载的区别 (部分内容转自竹木人)
    面向对象的基本概念
    PHP json_encode( ) 函数介绍
    js页面跳转常用的几种方式
    js中页面刷新和页面跳转的方法总结 [ 转自欢醉同学 ]
  • 原文地址:https://www.cnblogs.com/choii/p/14604608.html
Copyright © 2020-2023  润新知