• 基于AppDomain的插件开发调用域回调(二)


    基于AppDomain"插件式"开发中,我们在别人的原理上,实现了插件原型。

    但是,我们在执行 string Run(string args, Action action) 方法时,

    MessageBox.Show(loader.Run("111", () => { MessageBox.Show(AppDomain.CurrentDomain.FriendlyName); }));

    显示的AppDomain为远程的插件域,如图:

    如果我们想区分开, 对于默认的, 要求在调用域执行。 规定的:如RemoteAction 在插件域执行呢? 下面我们尝试解决:

    原来的代理:

    public class PluginLoader : TypeLoader, IPlugin

    {

    public string Run(string args, Action action)

    {

    return this.RemotePlugin.Run(args, action);

    }

    }

    我们做如下修改:

    public string Run(string args, Action action)

    {

    //本地域执行

    return this.RemotePlugin.Run(args, action.CreateRemoteAppDomainProxy());

    }

    其中:RemoteActionProxy为:

    /// <summary>

    ///方法域间代理类

    /// </summary>

    public class RemoteActionProxy : MarshalByRefObject

    {

    private Action action;

    private RemoteActionProxy()

    {

    }

    private RemoteActionProxy(Action action)

    {

    this.action = action;

    }

    public void Execute()

    {

    this.action();

    }

    public static Action CreateProxyAction(Action action)

    {

    var proxy = new RemoteActionProxy(action);

    return proxy.Execute;

    }

    }

    扩展帮助类:

    public static class RemoteDomainHelper

    {

    public static Action CreateRemoteAppDomainProxy(this Action action)

    {

    return RemoteActionProxy.CreateProxyAction(action);

    }

    public static Func<T> CreateRemoteAppDomainProxy<T>(this Func<T> func)

    {

    return RemoteFuncProxy<T>.CreateProxyFunc(func);

    }

    }

    再次执行一下,看一下域名,已经显示在主域中执行了。如图:

    最后, 我们可能也有需求, 要示在目标插件域执行的。 区分一下, 声明新类型,并实现代理:

    /// <summary>

    ///远程方法

    /// </summary>

    public delegate void RemoteAction();

     public string Run(string args, RemoteAction action)

    {

    //远程域执行,直接传递

    return this.RemotePlugin.Run(args, action);

    }

    速度测试:

                var watch = Stopwatch.StartNew();
                for(int i = 0; i < 10000; ++i)
                {
                    loader.Run("1");
                }
                watch.Stop();
                var ms1 = watch.Elapsed.TotalMilliseconds;
    
                watch.Restart();
                Action a = new Action(() => { });
                for (int i = 0; i < 10000; ++i)
                {
                    a();
                }
                watch.Stop();
                var ms2 = watch.Elapsed.TotalMilliseconds;
    
                Debug.Print("跨域:{0},   本地:{1}", ms1, ms2);
    
                //跨域:1032.3765,   本地:0.2803
    
    
                watch.Restart();
                for (int i = 0; i < 10000; ++i)
                {
                    loader.Run("1", a);
                }
                watch.Stop();
                ms1 = watch.Elapsed.TotalMilliseconds;
    
                watch.Restart();
    
                for (int i = 0; i < 10000; ++i)
                {
                    loader.Run("1", a.CreateRemoteAppDomainProxy());
                }
                watch.Stop();
                ms2 = watch.Elapsed.TotalMilliseconds;
    
                Debug.Print("跨域回调:插件域{0},   本域:{1}", ms1, ms2);
    
                //跨域回调:插件域4069.8274,   本域:4305.1899
    

      

    QQ:273352165 evlon#126.com 转载请注明出处。
  • 相关阅读:
    Android sdk + PhoneGap 配置
    一个解析url参数方法
    开始写笔记了~~
    Codevs 3305 水果姐逛水果街Ⅱ 倍增LCA
    Codevs 3304 水果姐逛水果街Ⅰ 线段树
    Cogs 1070. [焦作一中2012] 玻璃球游戏 带权并查集,逆序处理
    Bzoj 1901: Zju2112 Dynamic Rankings 主席树,可持久,树状数组,离散化
    Bzoj 2453: 维护队列 && Bzoj 2120: 数颜色 分块,bitset
    Uoj #131. 【NOI2015】品酒大会 后缀数组,并查集
    Tyvj P1463 智商问题 分块
  • 原文地址:https://www.cnblogs.com/evlon/p/plugin_action.html
Copyright © 2020-2023  润新知