使用MarshalByRefObject而不必加载在第二个AppDomain中加载的程序集

时间:2015-01-08 19:38:04

标签: c# .net appdomain marshalbyrefobject

我有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;
    }
}

0 个答案:

没有答案