beetlex-io / XRPC

dotnet high performance remote interface and delegate invoke(RPC) communication components,support millions RPS remote interface method invokes
Apache License 2.0
84 stars 22 forks source link

关于Xrpc的XRPCServer.EventToken设计解耦的问题 #24

Open snikeguo opened 4 years ago

snikeguo commented 4 years ago

现有的是通过唯一的静态属性XRPCServer.EventToken 去获取当前的连接信息的。不够优雅~~ 我有个思路,你看下:

using System;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    interface IMyInterFace
    {
        Task HelloWorld(string s);
    }

    //服务端这么设计:
    //MyInterFaceImpl继承IMyInterFace和“当前连接会话”的类(XRPCEventToken)
    //这个MyInterFaceImpl具体的对象也是你Xrpc底层反射创建的,创建好后,先转成XRPCEventToken 赋值好当前的“链接信息”等信息
    //最后调用MyInterFaceImpl实例的HelloWorld方法
    //这样解决了XRPCServer.EventToken的静态属性的问题。
    class MyInterFaceImpl :  XRPCEventToken,IMyInterFace
    {
        public Task HelloWorld(string s)
        {
            var 当前的Session = this.Session;//这个字段来自XRPCEventToken
            var 当前的Server = this.Server;
            var 当前的Request = this.Request;
            //...业务操作。
            return Task.CompletedTask;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}
snikeguo commented 4 years ago

我的简单实现。已经测试可以用

using System;
using System.Reflection;
using System.Threading.Tasks;

namespace ConsoleApp1
{

    interface IMyInterFace
    {
        Task HelloWorld(string s);
    }
    class MyInterFaceImpl : ServerInfo,IMyInterFace
    {
        public Task HelloWorld(string s)
        {
            Console.WriteLine($"Hello World!{s}");
            return Task.CompletedTask;
        }
    }
    class ServerInfo
    {
        public string Ipv4 { get; set; } = "127.0.0.1";
    }
    class Program
    {
        static void Main(string[] args)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();

            var v = assembly.GetTypes();

            //假设到这里 已经知道了要创建那个类型的对象了,

            Type MyInterFaceImplType = assembly.GetType("ConsoleApp1.MyInterFaceImpl");//获取要创建对象的类型

            Object MyInterFaceImplInstance = assembly.CreateInstance(MyInterFaceImplType.FullName);//创建对象

            ((ServerInfo)(MyInterFaceImplInstance)).Ipv4 = "666";//这里把链接信息赋给创建好的对象
            var needcallmi = MyInterFaceImplType.GetMethod("HelloWorld");//获取需要调用的mathodInfo
            needcallmi.Invoke(MyInterFaceImplInstance, new object[] { "123" });//call
        }
    }
}
snikeguo commented 4 years ago

image

beetlex-io commented 4 years ago

这个主要看控制器的实例模式吧,如果每次调用都实例化这种设计是可行,如果是单实例则不好用了。

snikeguo commented 4 years ago

单实例的话,就不用创建对象了,找到最前面第一次创建的对象,更新当前的连接信息即可。 顺便说一句,用户如果继承连接信息类的话,就赋值当前连接信息操作,如果用户没继承连接信息类,只是继承了IMyInterface(底层实现强转成父类,肯定是null),就不操作,说明用户不需要连接信息。

beetlex-io commented 4 years ago

单实例是所有用户共享实例,无法直接更新,这样会存在线程安全问题。

snikeguo commented 4 years ago

那就单例模式下不允许这么做。实例模式下才允许