2015-02-15 2 views
2

Я пытаюсь создать фрейм плагина и загружать зависимости путем отражения в C#. Моя текущая реализация такова:C# Сборка Create Instance в дочернем домене

public interface IPlugin : IDisposable 
{ 
    void Run(); 
} 

public interface IPluginProxy : IDisposable 
{ 
    void RunProxy(); 
    void LoadDependencies(string pluginDirectoryPath, AppDomain pluginDomain); 
} 

public class PluginProxy : MarshalByRefObject, IPluginProxy, IDisposable 
    { 
     private List<IPlugin> pluginTypes = null; 


     public void ProcessProxy() 
     { 
      //loop thorough plugin types and call Run on all plugins 
      foreach(var pluginType in pluginTypes) 
      { 
       pluginType.Run(); 
      } 
     } 

     public void LoadDependencies(string pluginDirectoryPath, AppDomain pluginDomain) 
     { 
      pluginTypes = Utility.LoadAssembliesAndGetPluginTypes(pluginDirectoryPath, pluginDomain);    
     } 

     //TODO: 
     public void Dispose(){} 

    } 

public Class Utility 
{ 
    public static List<IPlugin> LoadAssembliesAndGetPluginTypes(string pluginDirectoryPath, AppDomain pluginDomain) 
    { 
     try 
     { 
      var pluginTypes = new List<IPlugin>(); 
      var pluginsDirectory = new DirectoryInfo(pluginDirectoryPath); 
      var files = pluginsDirectory.GetFiles("*.dll", SearchOption.TopDirectoryOnly); 

      foreach (FileInfo file in files) 
      { 
       // Load the assembly into the child application domain. 
       Assembly assembly = pluginDomain.Load(AssemblyName.GetAssemblyName(file.FullName)); 
       var iPluginTypes = zGetTypes(assembly); 
       pluginTypes.AddRange(iPluginTypes.ToList()); 
      } 

      return pluginTypes; 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
    } 

    private static IEnumerable<IPlugin> zGetTypes(Assembly assembly) 
    { 
     var myPlugins = from y in assembly.GetTypes() 
          where y.IsClass && y.GetInterface("IPlugin") != null && 
            y.GetConstructor(Type.EmptyTypes) != null 
          select Activator.CreateInstance(y) as IPlugin; 
     return myPlugins; 
    } 
} 

У меня есть служба Windows, которая создает новый домен приложения. Затем он получает PluginProxy и вызывает LoadDependencies и ProcessProxy. Заметьте, что я пытаюсь загрузить зависимости в дочерний домен.

Проблема с методом zGetTypes. Метод способен находить типы IPlugin (это показывает intellisense). Однако типы не инициализируются (null), даже если вы вызываете Activator.CreateInstance.

Обратите внимание: zGetTypes не может создать экземпляр типа IPlugin, если я в дочернем домене.

Монтажная сборка = плагинDomain.Load (AssemblyName.GetAssemblyName (file.FullName));

Если я не создаю отдельный appdomain и просто загружаю сборку в основной appdomain, создается создание экземпляра экземпляра. В моем случае приложение appdomain создает дочернее приложение. Я хочу взять на себя ответственность за загрузку сборок плагина в прокси. Прокси получается из MarshalByRefObject, поэтому я могу создать экземпляр и развернуть его со стороны службы Windows.

Служба затем делегирует управление загрузками и жизненным циклом плагинов на прокси. Прокси-сервер получит контекст дочернего appdomain через параметр метода LoadDependencies.

Любые идеи, почему бы не создать экземпляр (ы) IPlugin?

ответ

0

Мне удалось решить проблему, вызывая домен на уровне прокси. В моей службе окна, я создавал экземпляр плагина прокси следующим образом:

IPluginProxy pluginProxy = IPluginProxy) 
(pluginDomain 
.CreateInstanceFromAndUnwrap(directory.FullName + "\\Utility.Common.dll", 
typeof(PluginProxy).FullName)); 

В моем призыве к LoadAssemblies, я проходил ребенок AppDomain в качестве параметра: LoadDependencies (строка pluginDirectoryPath, AppDomain pluginDomain);

Это было необязательно, поскольку прокси-сервер был в контексте дочернего домена. Это решило проблему.