AppDomain Unload
От: codenet Россия  
Дата: 05.01.15 17:24
Оценка:
Доброе время суток Коллеги!

возникла некоторирая сложность при работе и не приходит в голову как разрезолвить данную проблему

работа с плагинами
есть интерфейс :
1 сборка
   public interface IPlugin 
    {       
        bool Start();
        event EventHandler<LogEventArgs>  OnLog;
    }
 public class LogEventArgs : EventArgs
    {
        public string Message { get; set; }
        public Exception Error { get; set; }
    }


2 сборка сам плагин

 public class Test: MarshalByRefObject,IPlugin
    {      
        public bool Start()
        {
            if(OnLog!=null)
                OnLog(this,new LogEventArgs(){Message = "Started"});
            return true;
        }     

        public event EventHandler<LogEventArgs> OnLog;
    }


3 сборка
использование плагина
  class Program
    {
        static void Main(string[] args)
        {
            var pl = new PluginController();
            Console.WriteLine("before load...");
            foreach (var each in AppDomain.CurrentDomain.GetAssemblies().Where(x => typeof(IPlugin).IsAssignableFrom(x.GetTypes().FirstOrDefault())))
            {
                Console.WriteLine(each.FullName);
            }
            pl.LoadAllPlugin();
            Console.WriteLine("after load...");
            foreach (var each in AppDomain.CurrentDomain.GetAssemblies().Where(x => typeof(IPlugin).IsAssignableFrom(x.GetTypes().FirstOrDefault())))
            {
                Console.WriteLine(each.FullName);
            }
            pl.UnloadAllPlugin();
            Console.WriteLine("after unload...");
            foreach (var each in AppDomain.CurrentDomain.GetAssemblies().Where(x => typeof(IPlugin).IsAssignableFrom(x.GetTypes().FirstOrDefault()) ))
            {
                Console.WriteLine(each.FullName);
            }
            Console.ReadKey();
        }
    }

 public class PluginController
    {
         private List<PluginObject> plList;

        public PluginController()
        {
            plList = new List<PluginObject>();
        }
        public void LoadAllPlugin()
        {
            AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += CurrentDomain_ReflectionOnlyAssemblyResolve;
            var pluginsFolder = WebConfigurationManager.AppSettings["PluginDirectory"];            
            var domainInfo = new AppDomainSetup
                {
                    ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
                    PrivateBinPath = pluginsFolder
                };
             var domain = AppDomain.CreateDomain("PluginLoader", null, domainInfo);
            foreach (var plugin in Directory.GetFiles(pluginsFolder, "B*.dll", SearchOption.TopDirectoryOnly))
            {
                 var newAssembly = Assembly.ReflectionOnlyLoadFrom(plugin);
                var types = newAssembly.GetTypes();
                var tx = types.FirstOrDefault(t => typeof(IPlugin).IsAssignableFrom(t));
                if (tx == null) return;

                var exe = domain.CreateInstanceFromAndUnwrap(tx.Assembly.Location,tx.FullName) as IPlugin;

                if (exe != null)
                {
                    exe.OnLog += exe_OnLog;
                    exe.Start();
        plList.Add(new PluginObject(){Domain = domain,plugin = exe});
                }              
            }
        }

        Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
        {
            return Assembly.ReflectionOnlyLoad(args.Name);
        }

        public void UnloadAllPlugin()
        {
     plList.ForEach(x=>AppDomain.Unload(x.Domain));
        }
        static void exe_OnLog(object sender, LogEventArgs e)
        {
            Console.WriteLine(e.Message);
        }

    }


В итоге вижу :
before load...
Started
after load...
IPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
after unload...
IPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

проблема в том что плагин как мы видим не выгрузился.
в чем и заключается вопрос,как правильнее быть?
p\s но если попытаюсь после анлоада обратиться к нему будет исключение что он выгружен,но тогда почему мы видим что это не так на консоли
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.