基于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

 

  

 

 

 

posted @ 2012-10-12 10:28  阿牛  阅读(887)  评论(1编辑  收藏  举报