插件架构 - 如何在另一个AppDomain中的插件之间进行通信?

时间:2013-03-02 09:54:08

标签: c# plugins

插件之间的通信存在问题。每个插件都加载到一个单独的AppDomain中。我还想了解一些关于插件的信息(名称,版本,..)。

我使用this tutorial创建了我的应用程序。

在教程中是使用raiseEvent()的方法但是当我调用它时没有任何反应..我想获得插件的名称,它位于新的appDomain中,而教程中的事件不起作用。

我发现了很多文章,但对我来说没什么用。

主应用程序调用插件管理器:

         public static void Main(string[] args)
    {
        //Using block will make sure that the cleanup code of PluginHost is executed
        using (PluginHost host = new PluginHost())
        {
            host.PluginChange += new PluginEventHandler(host_PluginChange);
            host.RunPlugin(@"C:\Plugins2\WindowsFormsApplication1.dll");
            Console.ReadKey();
        }
    }

    static void host_PluginChange(string message)
    {
        Console.WriteLine(message);
    }

来源示例事件:

        event PluginEventHandler _pluginEvent;
    public event PluginEventHandler PluginChange
    {
        add { _pluginEvent += value; }
        remove { _pluginEvent -= value; }
    } 

事件致电:

        private void RaiseEvent(string message)
    {
        if (_pluginEvent != null)
            _pluginEvent(message);
    } 

创建appDomain ant的方法调用启动方法,其中event为:

        public void RunPlugin(string path)
    {
        //Creating the appdomain manager
        AppDomainManager manager = new AppDomainManager();
        //Check if there is any *.dll.config file
        string configFileName = string.Format("{0}.config", path);
        AppDomainSetup setup = new AppDomainSetup();
        //Enable shadow copying, so the Plugin files are not locked
        setup.ShadowCopyFiles = "true";
        setup.LoaderOptimization = LoaderOptimization.MultiDomain;
        //if the config file exists, load it into the appdomain
        if (File.Exists(configFileName))
            setup.ConfigurationFile = configFileName;
        //Creating the AppDomain & adding a reference to it in the _appDomains collection.
        AppDomain domain = manager.CreateDomain(String.Format("AD-{0}", _appDomains.Count), null, setup);
        _appDomains.Add(domain);
        /*
         * This important.
         * Here we are initiating an instance of PluginHost inside the new AppDomain.
         * this instance will give us control from the host appdomain to load & run the plugins inside the new appdomain
         */
        PluginHost remoteHost = domain.CreateInstanceAndUnwrap(Assembly.GetAssembly(typeof(PluginHost)).FullName, typeof(PluginHost).ToString()) as PluginHost;
        RaiseEvent(String.Format("Hello from domain {0}", domain.FriendlyName));

        // Here we run every plugin in a separate thread
        ThreadPool.QueueUserWorkItem(
            delegate(object state)
            {
                try
                {
                    //calling the PluginHost object created in the other appdomain.
                    remoteHost.Launch(path, domain);
                }
                catch (Exception ex)
                {
                    _appDomains.Remove(domain);
                    AppDomain.Unload(domain);
                }
            });
    } 

调用事件的方法:(raiseEvent)

       void Launch(string assemblyPath, AppDomain domain)
    {
        //Loading the assembly file into the appdomain
        Assembly pluginAssembly = domain.Load(AssemblyName.GetAssemblyName(assemblyPath));
        domain.AssemblyResolve += delegate(object sender, ResolveEventArgs args)
        {
            AppDomain d = sender as AppDomain;
            string path = Path.Combine(@"C:\Plugins\References", args.Name.Split(',')[0] + ".dll");
            return d.Load(path);
        };

        RaiseEvent(String.Format("Hello from domain {0}", domain.FriendlyName));
        //Searching for Plugin types inside the loaded assembly
        foreach (Type type in pluginAssembly.GetTypes())
        {
            if (!type.IsClass) continue;

            if (type.FindInterfaces(delegate(Type t, object filter) { return t == filter as Type; }, typeof(IPlugin)).Length > 0)
            {
                //Using block will make sure that the plugins will run cleanup code after execution
                using (IPlugin plugin = pluginAssembly.CreateInstance(type.ToString()) as IPlugin)
                {
                    plugin.Run("Here we place some params for the external plugin");
                }
            }
        }
    }

0 个答案:

没有答案