zoukankan      html  css  js  c++  java
  • 基于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 转载请注明出处。
  • 相关阅读:
    OutputCache 缓存key的创建 CreateOutputCachedItemKey
    Asp.net Web Api源码调试
    asp.net mvc源码分析DefaultModelBinder 自定义的普通数据类型的绑定和验证
    Asp.net web Api源码分析HttpParameterBinding
    Asp.net web Api源码分析HttpRequestMessage的创建
    asp.net mvc源码分析ActionResult篇 RazorView.RenderView
    Asp.Net MVC 项目预编译 View
    Asp.net Web.config文件读取路径你真的清楚吗?
    asp.net 动态创建TextBox控件 如何加载状态信息
    asp.net mvc源码分析BeginForm方法 和ClientValidationEnabled 属性
  • 原文地址:https://www.cnblogs.com/evlon/p/plugin_action.html
Copyright © 2011-2022 走看看