前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2019-7-30-使用DispatchProxy生成代理

2019-7-30-使用DispatchProxy生成代理

作者头像
黄腾霄
发布2020-06-10 14:43:54
3410
发布2020-06-10 14:43:54
举报
文章被收录于专栏:黄腾霄的博客

最近在做RPC的时候遇到了一点问题,接口I的调用方在进程A,而实现方在进程B。那么要完成进程A中的操作,必然要在进程A生成接口I的动态代理。怎么办呢?这里使用DispatchProxy来进行实现


DispatchProxy是一个抽象类,使用方法非常简单。只需要继承这个类,重写他的Invoke方法,这里我们可以从参数获得代理被调用方法的MethodInfo以及其传入的参数。这里我们先试着打印他的方法名称

代码语言:javascript
复制
    public class ADispatchProxy : DispatchProxy
    {
        protected override object Invoke(MethodInfo targetMethod, object[] args)
        {
            Console.WriteLine(targetMethod.Name);
            return null;
        }
    }

接着我们考虑接口IA

代码语言:javascript
复制
	public interface IA
    {
        void Foo(string a);
    }

试着创建一个IA的代理,这里用到了静态方法DispatchProxy.Create<IA, ADispatchProxy>()

代码语言:javascript
复制
    class Program
    {
        static void Main(string[] args)
        {
            var a = DispatchProxy.Create<IA, ADispatchProxy>();
            a.Foo("123");
        }
    }

OK,我们通过一个动态代理完成了接口的调用。

那么现在我们再试着通过容器注入一个实现。这里是通过ConcurrentDictionary做的简单容器

代码语言:javascript
复制
	/// <summary>
    /// 用于模块内部使用的IOC容器
    /// </summary>
    internal class Container
    {
        private static readonly Lazy<Container> Instance = new Lazy<Container>();
        public static Container Current => Instance.Value;

        private readonly ConcurrentDictionary<Type, object> _dictionary = new ConcurrentDictionary<Type, object>();

        /// <summary>
        /// 向容器中添加对象。
        /// </summary>
        /// <typeparam name="T">对象的指定类型。</typeparam>
        /// <param name="value">向容器中添加的对象实例。</param>
        public void Set<T>(T value)
        {
            _dictionary[typeof(T)] = value;
        }

        /// <summary>
        /// 从容器中获取指定类型的对象实例。
        /// </summary>
        /// <typeparam name="TService">指定类型。</typeparam>
        /// <returns>容器中指定类型的对象实例。</returns>
        public TService Get<TService>()
        {
            var type = typeof(TService);
            return (TService) Get(type);
        }

        /// <summary>
        /// 从容器中获取指定类型的对象实例。
        /// </summary>
        /// <typeparam name="TService">指定类型。</typeparam>
        /// <returns>容器中指定类型的对象实例。</returns>
        public object Get(Type type)
        {
            if (_dictionary.TryGetValue(type, out var value))
            {
                return value;
            }

            return null;
        }
    }

而在调用端代码更改如下,我们向容器中注入IA的实现A,并且在ADispatchProxy的invoke方法中获取实例,进行调用

代码语言:javascript
复制
    class Program
    {
        static void Main(string[] args)
        {
            Container.Current.Set<IA>(new A());
            var a = DispatchProxy.Create<IA, ADispatchProxy>();
            a.Foo("123");
        }
    }


    public interface IA
    {
        void Foo(string a);
    }

    public class A : IA
    {
        public void Foo(string a)
        {
            Console.WriteLine(a);
        }
    }

    public class ADispatchProxy : DispatchProxy
    {
        protected override object Invoke(MethodInfo targetMethod, object[] args)
        {
            var type = targetMethod.DeclaringType;
            var o = Container.Current.Get(type);
            if (o != null) 
            {
                Console.WriteLine(targetMethod.Name);
                return targetMethod.Invoke(o, args);
            }

            return null;
        }
    }

可以看到在动态代理中完成了实例方法的调用。我们之后再将参数信息通过IPC传递给进程B,就可以实现RPC了。

参考链接:

DispatchProxy Class (System.Reflection) - Microsoft Docs


本文会经常更新,请阅读原文: https://xinyuehtx.github.io/post/%E4%BD%BF%E7%94%A8DispatchProxy%E7%94%9F%E6%88%90%E4%BB%A3%E7%90%86.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名黄腾霄(包含链接: https://xinyuehtx.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-07-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档