插件之间的通信存在问题。每个插件都加载到一个单独的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");
}
}
}
}