@Ksarrik

Как решить проблему динамического подключения сборок расширяемого приложения?

Добрый день. Столкнулся с следующей проблемой:
Хотел сделать приложение, которое проверяет папку на наличие сборок-подключаемых модулей и динамически их подгружает. Когда подключаемые сборки не содержать ссылок на другие сборки, все работает нормально. Но когда сборки ссылаются на методы других локальных сборок выскакивает исключение, что сборка не найдена, что логично, поскольку сборка не загружена в домен. Просто коммерческие приложения ( например Revit) спокойно обрабатывают такие ссылки, достаточно в основной сборке реализовать необходимые интерфейсы, и если моя сборка содержит ссылки на другие сборки в процессе выполнения метода интерфейса, то у них никаких исключений не возникает и методы вызываются. Вопрос как можно решить данную проблему и как решают эту проблему коммерческие приложения?
Подробнее, поясняющий пример:
Код основного приложения в папке Modules которого содержатся сборки StarterLib.dll и HelloWorld.dll:
class Program
    {
        static void Main(string[] args)
        {
            LoadAssembliesModules();
            Console.ReadLine();
        }
        private static void LoadAssembliesModules()
        {
            string modulespath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "//Modules";

            var AddInAssemblies = Directory.EnumerateFiles(modulespath, "*.dll");
           
            var AddInTypes = from file in AddInAssemblies
                             let assembly = Assembly.LoadFile(file)
                             from t in assembly.ExportedTypes // Открыто экспортируемые типы
                                                              // Тип может использоваться, если это класс, реализующий IStart
                             where t.IsClass &&
                                         typeof(IStart).GetTypeInfo().IsAssignableFrom(t.GetTypeInfo())
                             select t;
            
            foreach (Type t in AddInTypes)
            {
                    IStart ai = (IStart)Activator.CreateInstance(t);

                    if (ai != null)
                    {
                        ai.Start();
                    }                
            }
        }
    }

Код сборки StarterLib.dll ссылающейся на HelloWorld.dll:
public class Class1: IStart
    {
        public void Start()
        {
            Console.WriteLine("Hello");
            //Не работает если убрать комментарии ниже:
            //Hello h = new Hello();
            //h.StartHello();
        }       
    }

Код сборки HelloWorld.dll:
public class Hello
    {
        public void StartHello()
        {
            System.Windows.Forms.MessageBox.Show("Hello World");
        }        
    }
  • Вопрос задан
  • 62 просмотра
Решения вопроса 2
petermzg
@petermzg
Самый лучший программист
Все просто. Реализуйте у себя код
AppDomain.AssemblyResolve += OnAssemblyResolve;
И в OnAssemblyResolve подгружайте в домен запрашиваемые сборки
Ответ написан
@Ksarrik Автор вопроса
Вроде бы нашел решение, оказалось на удивление простым: для автоматического обнаружения сборок достаточно было в config основного приложения добавить папку в которой искать необходимые сборки.
А именно:
<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="Modules"/>
    </assemblyBinding>
  </runtime>
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
freeExec
@freeExec
Участник OpenStreetMap
Вызываете метод assembly.GetReferencedAssemblies(); и получаете сборки от которых он зависит. И так рекурсивно по всем сборкам, получаете их пул и грузите их.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
ПРОФЭЛИТ Казань
от 100 000 до 170 000 ₽
Mystery Tag Новосибирск
от 80 000 до 110 000 ₽
GD Company Санкт-Петербург
от 120 000 до 150 000 ₽
02 апр. 2020, в 15:54
1000 руб./за проект
02 апр. 2020, в 15:48
10000 руб./за проект