AppDomain.Load() fails with FileNotFoundException

前端 未结 2 1342
难免孤独
难免孤独 2021-02-03 13:01

I\'m trying to load my plugin dll into separate AppDomain, but Load() method fails with FileNotFoundException. Moreover, it seems like setting PrivateBinPath property of AppDoma

2条回答
  •  粉色の甜心
    2021-02-03 14:01

    when you load an assembly into the AppDomain in that way, it is the current AppDomain's PrivateBinPath that is used to find the assembly.

    For your example, when I added the following to my App.config it ran fine:

    
      
        
      
    
    

    This is not very useful to you though.

    What I did instead was to create a new assembly that contained the IPostPlugin and IPluginsHost interfaces, and also a class called Loader that looked like this:

    public class Loader : MarshalByRefObject
    {
        public IPostPlugin[] LoadPlugins(string assemblyName)
        {
            var assemb = Assembly.Load(assemblyName);
    
            var types = from type in assemb.GetTypes()
                    where typeof(IPostPlugin).IsAssignableFrom(type)
                    select type;
    
            var instances = types.Select(
                v => (IPostPlugin)Activator.CreateInstance(v)).ToArray();
    
            return instances;
        }
    }
    

    I keep that new assembly in the application root, and it doesn't need to exist in the plugin directories (it can but won't be used as the application root will be searched first).

    Then in the main AppDomain I did this instead:

    sandbox.Load(typeof(Loader).Assembly.FullName);
    
    Loader loader = (Loader)Activator.CreateInstance(
        sandbox,
        typeof(Loader).Assembly.FullName,
        typeof(Loader).FullName,
        false,
        BindingFlags.Public | BindingFlags.Instance,
        null,
        null,
        null,
        null).Unwrap();
    
    var plugins = loader.LoadPlugins(AssemblyName.GetAssemblyName(f.FullName).FullName);
    
    foreach (var p in plugins)
    {
        p.Init(this);
    }
    
    _PostPlugins.AddRange(plugins);
    

    So I create an instance of the known Loader type, and then get that to create the plugin instances from within the plug-in AppDomain. That way the PrivateBinPaths are used as you want them to be.

    One other thing, the private bin paths can be relative so rather than adding d.FullName you could add pluginsDir + Path.DirectorySeparatorChar + d.Name to keep the final path list short. That's just my personal preference though! Hope this helps.

提交回复
热议问题