码迷,mamicode.com
首页 > 其他好文 > 详细

<八>实现服务代理,利用特性自动封装服务路由

时间:2021-04-05 12:19:02      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:typeof   需要   request   html   ESS   client   space   dict   解析   

上一节我们把服务路由改由客户端传入了,但是每次都要在客户端这里写命名空间啥的比较麻烦,这应该在写方法的时候就应该规定好。这时候特性就派上用场了。

想要了解特性的使用的请参考这篇文章:【.net 深呼吸】自定义特性(Attribute)的实现与检索方法

1、首先添加两个特性类,一个用于接口,一个用于方法

namespace AidenGRPC.RPCBase.CommonAttribute
{
    [AttributeUsage(AttributeTargets.Interface, Inherited = false, AllowMultiple = false)]
    public class ServiceRouteAttribute : Attribute
    {
        public ServiceRouteAttribute(string _namespace,string _classname)
        {
            NameSpace = _namespace;
            ClassName = _classname;
        }

        public string NameSpace { get; set; }
        public string ClassName { get; set; }
       
    }
}
namespace AidenGRPC.RPCBase.CommonAttribute
{
    [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
    public class ServerMethodAttribute : Attribute
    {
        public ServerMethodAttribute(string _methodname)
        {
            MethodName = _methodname;
        }
        public string MethodName { get; set; }
    }
}

2、添加一个存放接口的程序集,新增一个接口并添加上特性,绑定好此接口的实现类和实现方法名。

namespace AidenGRPC.IModule
{
    [ServiceRoute("AidenGRPC.Module", "SayHelleServer")]
    public interface ISayHelleServer
    {
        [ServerMethod("SayHello")]
        string SayHello(string name);
    }
}

 3、接下来就是要解析这个接口的特性,并将解析完的特性添加到dictionary里面并作为参数直接调用服务端服务。

       那么在给接口的实例调用sayhello的时候自动反射调用服务端服务呢?Castle.DynamicProxy这个dll里提供了一种叫动态代理的东西。

  ProxyGenerator这个类实现了一个叫 CreateInterfaceProxyWithoutTarget的方法,这个方法需要传入一个实现IInterceptor接口的类。

       这样,只需要将接口的实现绑定成这个方法,就可以完成自动解析attribute的功能。

    public class ServicesProxy
    {
        private static ProxyGenerator generator = new ProxyGenerator();
        public static TInterface GetService<TInterface>(string ip, int port) where TInterface : class
        {
            return generator.CreateInterfaceProxyWithoutTarget<TInterface>(new GRPCInterceptor(ip, port));
        }
    }
public class GRPCInterceptor : IInterceptor
    {
        public string Ip { get; set; }
        public int Port { get; set; }
        public GRPCInterceptor(string ip, int port)
        {
            Ip = ip;
            Port = port;
        }
        public void Intercept(IInvocation invocation)
        {
            Dictionary<string, string> dictionary = new Dictionary<string, string>();
            ServerMethodAttribute methodAttr = invocation.Method.GetCustomAttributes<ServerMethodAttribute>().FirstOrDefault<ServerMethodAttribute>();
            ServiceRouteAttribute routeAttr = invocation.Method.DeclaringType.GetCustomAttributes<ServiceRouteAttribute>().FirstOrDefault<ServiceRouteAttribute>();
            if (methodAttr != null)
            {
                if (!string.IsNullOrWhiteSpace(methodAttr.MethodName))
                {
                    dictionary.Add(ServicesRoute.METHODNAME, methodAttr.MethodName);
                }
            }
            if (routeAttr != null)
            {
                if (!string.IsNullOrWhiteSpace(routeAttr.NameSpace))
                {
                    dictionary.Add(ServicesRoute.NAMESPACE, routeAttr.NameSpace);
                }
                if (!string.IsNullOrWhiteSpace(routeAttr.ClassName))
                {
                    dictionary.Add(ServicesRoute.CLASSNAME, routeAttr.ClassName);
                }
            }
            ParameterInfo[] parameters = invocation.Method.GetParameters();
            for (int i = 0; i < parameters.Length; i++)
            {
                ParameterInfo parameterInfo = parameters[i];
                if (!dictionary.ContainsKey(parameterInfo.Name))
                {
                    dictionary.Add(parameterInfo.Name, invocation.Arguments[i].ToString());  //不完善,如果参数是个类,那么这里需要用转成json再添加
                }
                else
                {
                    dictionary[parameterInfo.Name] = invocation.Arguments[i].ToString();
                }
            }
            if (invocation.Method.ReturnType == typeof(void)))
            {
                new Request(Ip, Port).Invoke(dictionary);
                return;
            }
            GrpcResponse responseMsg = new Request(Ip, Port).Invoke(dictionary);
            invocation.ReturnValue = responseMsg.ResponseMsg;
        }
    }

4、依赖注入,我们在客户端main函数里面直接注入一下,试试看效果。

  static void Main(string[] args)
        {
            var serviceProvider = new ServiceCollection()
                 .AddSingleton(typeof(ISayHelleServer), ServicesProxy.GetService<ISayHelleServer>("127.0.0.1", 30052))
                 .BuildServiceProvider();
            var server = serviceProvider.GetService<ISayHelleServer>();
            string rp = server.SayHello("Aiden");
            Console.WriteLine(rp);
            Console.WriteLine("Press any key to exit client...");
            Console.ReadKey();
        }

5、运行试试看,如下图,能够走通,这样代理就完成了。

技术图片

 

 

 

 

 

<八>实现服务代理,利用特性自动封装服务路由

标签:typeof   需要   request   html   ESS   client   space   dict   解析   

原文地址:https://www.cnblogs.com/choii/p/14608975.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!