zoukankan      html  css  js  c++  java
  • <六>添加自定义服务模块寄宿到server中

    由上一节可以看到我们每次新增加一个服务都需要添加一个proto文件,并且需要手动生成服务端和客户端的代码。

    这样是不是很麻烦呢?那么可不可以定义一个公共的proto文件生成一个基础的方法,让所有的自定义方法都通过这个基础方法来执行自定义服务呢。

    我们动手看看。

    1、在上一节的基础上,在proto里面新增一个Invoke基础方法,定义两个公共参数。代码如下:

    syntax="proto3";
    
    package AidenGRPC.RPCBase;
    
    service TestServer {
      rpc GetFeature(Point) returns (Feature) {}
      rpc Invoke(GrpcRequest) returns (GrpcResponse){}
      }
    
    message GrpcRequest{
         string requestMsg=1;
     } 
    
     message GrpcResponse{
        string responseMsg=1;
     }
    
    
    message Point {
    int32 latitude = 1;
    int32 longitude = 2;
    }
    
    message Feature {
      string name = 1;
      Point location = 2;
    }

    2、双击此bat文件重新生成服务端和客户端类,TestServerBase类里面出现了一个新的方法,就是重新生成成功了。

    3、新建一个module类库来保存(给每一个模块单独新建一个module类库,后面每个模块可以单独部署,比如后台的服务就叫adminModule),我这里就随便命名了一个module。里面建了一个SayHelloServer的

     SayHelloSever里面建一个方法

      public class SayHelleServer
        {
            public string SayHello(string name)
            {
                return $"{name} Say Hello World";
            }
        }

     4、服务端新增实现Invoke方法,服务端引用module 项目,这样就把module的dll引入到server的bin目录下了。目的是为了简单的反射执行该方法。新增一个BulidServices的方法来反射执行SayHelloServer的SayHello方法

     public static T GetInvokeMethod<T>(GrpcRequest r)
            {
                try
                {
                    string nameSpace = "AidenGRPC.Module";
                    string className = "SayHelloServer";
                    string methodName = "SayHello";
                    //命名空间.类名,程序集               
                    object instance = Assembly.Load(nameSpace).CreateInstance(nameSpace + "." + className);
                    Type type = instance.GetType();
                    //加载类型
                    // Type type = Type.GetType(path);
                    //根据类型创建实例
                    object obj = Activator.CreateInstance(type, true);
                    //加载方法参数类型及方法
                    MethodInfo method = null;
                    if (r != null && !string.IsNullOrEmpty(r.RequestMsg))
                    {
                        //加载方法参数类型
                        Type[] paratypes = new Type[1];
                        paratypes[0] = r.RequestMsg.GetType();
    
                        method = type.GetMethod(methodName, paratypes); //加载有参方法
                        return (T)method.Invoke(obj, new object[] { r.RequestMsg })
                    }
                    else
                    {
                        //加载无参方法
                        method = type.GetMethod(methodName);
                        return (T)method.Invoke();
    } //类型转换并返回  } catch (Exception ex) { //发生异常时,返回类型的默认值。 return default(T); } }

    5、在实现方法中添加相关Invoke的实现

     public class TestImpl:AidenGRPC.RPCBase.TestServer.TestServerBase
        {
            public override Task<Feature> GetFeature(Point request, ServerCallContext context)
            {
                return Task.FromResult(new Feature { Name = "aiden", Location = request });
            }
    
            public override Task<GrpcResponse> Invoke(GrpcRequest r, ServerCallContext context)
            {
                GrpcResponse re = new GrpcResponse();
                re.ResponseMsg= BuildServices.GetInvokeMethod<string>(r);
                return Task.FromResult(re);
            }

    6、运行服务端,能够正常启动

    7、再客户端写调用Invoke服务的代码,由于服务端定死了Invoke指向的是Sayhello方法,那么我们传一个名字过去,SayHello方法返回的是“Aiden Say Hello World”

     Channel channel = new Channel("127.0.0.1:30052", ChannelCredentials.Insecure);
                var client = new AidenGRPC.RPCBase.TestServer.TestServerClient(channel) ;
                //Point p = new Point() { Latitude = 409146, Longitude = -88906 };
                //Feature f= client.GetFeature(p);
                GrpcRequest re = new GrpcRequest();
                re.RequestMsg = "Aiden";
    
                GrpcResponse rp = client.Invoke(re);
                Console.WriteLine(rp.ResponseMsg);
               // Console.WriteLine(string.Format("Name:{0},Latitude:{1},Longitude:{2}", f.Name, f.Location.Latitude, f.Location.Longitude));
                channel.ShutdownAsync().Wait();
                Console.WriteLine("Press any key to exit client...");
                Console.ReadKey();        

    运行一下客户端,效果如下:

    ok这样整个路都走通了,上面我把命名空间,类型,方法名,端口啥的都写死了,这肯定不行的,调用哪个方法应该由客户端传给服务端,服务端根据客户端想要调用的方法信息反射执行后返回相应的值

    下一节我们看怎么封装好一些。

  • 相关阅读:
    【Rust】无关联类型
    【Rust】trait克隆
    【Rust】trait动态返回
    【Rust】trait迭代器
    【Rust】特质trait
    【Rust】运算符重载
    【Rust】trait超集
    【Rust】trait删除
    【Rust】trait实现
    wpf之数据模板 安静点
  • 原文地址:https://www.cnblogs.com/choii/p/14530270.html
Copyright © 2011-2022 走看看