我有2个AppDomains
1: host
2: plugin
现在我有PluginLoader
继承MarshalByRefObject
,因为我想传回加载到该域的插件数量。
我使用它来使用domain.DoCallBack(new CrossAppDomainDelegate(loader.LoadPlugin));
在插件-AppDomain中加载插件
在插件-AppDomain中,我加载了一个引用EntityFramework的插件。
现在,当我在使用EntityFramework.dll
的插件-AppDomain中加载插件时,我的主机-AppDomain也想加载EntityFramework.dll
。
只有当我的PluginLoader
扩展MarshalByRefObject
时才会发生这种情况。
当PluginLoader
没有扩展MarshalByRefObject(即它被序列化以进行调用)时,host-AppDomain不想加载EntityFramework.dll
。
所以我的问题是: 是否可以使用MarshalByRefObject调用另一个AppDomain而无需加载其他AppDomain请求的所有程序集? 或者更一般地说:我如何调用AppDomain并传回一个值,而不必加载其他AppDomain请求的那些程序集?
以下是我的参考代码:
static void Main(string[] args)
{
var pluginPath = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath) + "\\Plugins";
var files = Directory.GetFiles(pluginPath, "*.dll")
.Where(f => f.EndsWith("ArtNet.dll")); // just want to test this one plugin atm
Console.WriteLine("Found {0} files", files.Count());
foreach (var file in files)
{
Console.WriteLine("Loading {0}", file);
Console.WriteLine("Creating AppDomain");
var setup = new AppDomainSetup();
setup.PrivateBinPath = pluginPath;
var domain = AppDomain.CreateDomain(file, null, setup);
var loader = new PluginLoader { File = file, HubUri = hubUri };
domain.DoCallBack(new CrossAppDomainDelegate(loader.LoadPlugin));
if (loader.NumberOfLoadedPlugins > 0)
{
Console.WriteLine("Loaded {0} plugins from {1}", loader.NumberOfLoadedPlugins, file);
appDomains.Add(file, domain);
}
else
{
Console.WriteLine("{0} did not contain any plugins, unloading AppDomain", file);
AppDomain.Unload(domain);
Console.WriteLine("Appdomain Unloaded for file {0}", file);
}
}
Console.ReadKey();
}
代理:
[Serializable]
public class PluginLoader : MarshalByRefObject
{
public string File { get; set; }
public string HubUri { get; set; }
public int NumberOfLoadedPlugins { get; set; }
public void LoadPlugin()
{
var plugins = new List<IPlugin>();
Console.WriteLine("Loading Assembly");
var pluginAssembly = Assembly.LoadFile(File);
Console.WriteLine("Assembly loaded");
var pluginTypes = pluginAssembly.ExportedTypes.Where(t => t.GetInterfaces().Any(i => i.Equals(typeof(IPlugin))));
Console.WriteLine("Found {0} types implementing IPlugin", pluginTypes.Count());
foreach (var pluginType in pluginTypes)
{
try
{
Console.WriteLine("Looking for a parameterless Constructor in {0}", pluginType.Name);
var constructor = pluginType.GetConstructor(Type.EmptyTypes);
if (constructor != null)
{
Console.WriteLine("Found a parameterless constructor");
var plugin = (IPlugin)constructor.Invoke(null);
plugins.Add(plugin);
Console.WriteLine("Plugin of type {0} created", pluginType.Name);
plugin.StartAsync(HubUri).Wait();
Console.WriteLine("{0}.StartAsync({1}) called", pluginType.Name, HubUri);
}
else
Console.WriteLine("No Constructor found");
}
catch (Exception e)
{
Console.WriteLine("Exception occured");
Console.WriteLine(e);
}
}
PluginRegister.Plugins.AddRange(plugins);
NumberOfLoadedPlugins = plugins.Count;
}
}