我有插件之间的通信问题。每个插件都加载到单独的 AppDomain 中。我还想知道一些关于插件的信息(名称、版本、..)。
我使用本教程创建了我的应用程序。
在教程中是方法,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 的方法调用 Launch 方法,其中事件为:
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");
}
}
}
}