Проблема с референсами
От: abatishchev Россия http://godfather.net.ru
Дата: 05.04.07 09:25
Оценка:
Добрый день!
У меня возникла следующая проблема:

Есть приложение. Оно ищет свои плагины в папке /modules/
Там лежат библиотеки (А), определяемые общим интерфейсом.
Так же эти библиотеки имеют референсы на какие-то третьи библиотеки (Б), которые лежат рядом с ними. т.е. в папке /modules/.

Получается следующая схема:
App -> [inteface] -> dll А -> [reference] -> dll Б

При попытке вызвать из приложения метод из А, в котором есть ссылка на Б (по референсу, соответственно) появляется сообщение об ошибке, что библиотека Б не найдена! (ибо она ищется в папке с приложением а не в папке с библиотекой, которой её вызывает)

Вопрос: как указать приложению дополнительный путь для поиска указанных в референсе библиотек?

У меня сложилось впечатление, что причина этой проблемы в том, что референс указывается не по пути к файлу, а по имени библиотеки (MyLib, Version=1.0.1.0 Culture=neutral, PublicToken=a1b2c3d4e5)
И поиск происходит либо в AppBase (он же StartupPath, карчое ппака приложения) либо в GAC'е — если ни там ни там файла нет — выдаётся ошибка FileNotFound! Что делать?
Re: Проблема с референсами
От: Pavel_Agurov Россия  
Дата: 05.04.07 10:11
Оценка: 3 (1)
здесь
Автор(ы): Павел Агуров
Издательство: БХВ-Петербург
Цена: 292р.

При написании программ особенно важно не тратить время на поиск стандартных решений, а сосредоточиться на решении конкретной задачи, используя готовый эффективный код, разработанный и проверенный коллегой-программистом. В этой книге собраны лучшие


55. Перехват загрузки типов и модулей

Иногда возникает задача перехватить стандартную загрузку модулей и загрузть модуль, лежащий в определенной папке. Например, при решении проблемы локализации приложений, ресурсы могут лежать по папкам с именами языка и в зависимости от выбранного языка нужно загружать соответствующий модуль. Аналогичная задача может возникнуть при поиске модуля, содержащего нужный тип.
Событие AppDomain.CurrentDomain.TypeResolve вызывается, если системе (точнее говоря текущему домену) не удалось найти сборку, содержащую запрошенный тип. Событие AppDomain.CurrentDomain.AssemblyResolve вызывается, если системе не удалось найти запрошенную сборку.
Листинг 23 показывает пример использования этих событий. Главный модуль MainClass использует две сборки: ClassLibrary1, содержащую класс Class1 и ClassLibrary2, содержащую класс Class2. Главный модуль не имеет ссылки на первую сборку, поэтому при попытке найти тип Class1 будет вызываться обработчик TypeResolve, в котором мы загрузим нужную сборку самостоятельно. На вторую сборку ссылка имеется, но у нее выставлен тип CopyLocal=False, поэтому система не сможет определить местонахождение сборки и вызовет обработчик AssemblyResolve, в котором мы загрузим эту сборку самостоятельно.

Листинг 23. Трассировка исключенияОбработка событий AssemblyResolve и TypeResolve


using System;
using System.Reflection;

namespace ResolveAssembly
{
  class MainClass
  {
    static MainClass() 
    {
      AppDomain.CurrentDomain.TypeResolve += 
           new ResolveEventHandler(CurrentDomain_TypeResolve);
      AppDomain.CurrentDomain.AssemblyResolve +=
           new ResolveEventHandler(currentDomain_AssemblyResolve);
    }

    [STAThread]
    static void Main(string[] args)
    {
      Type t = Type.GetType("ClassLibrary1.Class1", false);
      if (t != null) 
      {
        Console.WriteLine(t.Name);
      }
      else
      {
        Console.WriteLine("Тип не найден");
      }


      ClassLibrary2.Class2 c2 = new ClassLibrary2.Class2();
      Console.WriteLine(c2.ToString());
    }

    private static Assembly CurrentDomain_TypeResolve(
                        object sender, ResolveEventArgs args)
    {
      Console.WriteLine("Ищу тип: {0}...", args.Name);

      if (args.Name.Equals("ClassLibrary1.Class1")) 
      {
        return Assembly.LoadFrom(
                 @"..\ClassLibrary1\bin\ClassLibrary1.dll");
      }

      return null;
    }

    private static Assembly currentDomain_AssemblyResolve(
                         object sender, ResolveEventArgs args)
    {
      Console.WriteLine("Ищу сборку {0}...", args.Name);
      if (args.Name.IndexOf("ClassLibrary2") >= 0) 
      {
        return Assembly.LoadFrom(
                  @"..\ClassLibrary2\bin\ClassLibrary2.dll");
      }
      return null;
    }
  }
}
Re[2]: Проблема с референсами
От: abatishchev Россия http://godfather.net.ru
Дата: 05.04.07 10:27
Оценка:
Здравствуйте, Pavel_Agurov, Вы писали:

P_A>здесь
Автор(ы): Павел Агуров
Издательство: БХВ-Петербург
Цена: 292р.

При написании программ особенно важно не тратить время на поиск стандартных решений, а сосредоточиться на решении конкретной задачи, используя готовый эффективный код, разработанный и проверенный коллегой-программистом. В этой книге собраны лучшие


P_A>55. Перехват загрузки типов и модулей


P_A>Иногда возникает задача перехватить стандартную загрузку модулей и загрузть модуль, лежащий в определенной папке. Например, при решении проблемы локализации приложений, ресурсы могут лежать по папкам с именами языка и в зависимости от выбранного языка нужно загружать соответствующий модуль. Аналогичная задача может возникнуть при поиске модуля, содержащего нужный тип.

P_A>Событие AppDomain.CurrentDomain.TypeResolve вызывается, если системе (точнее говоря текущему домену) не удалось найти сборку, содержащую запрошенный тип. Событие AppDomain.CurrentDomain.AssemblyResolve вызывается, если системе не удалось найти запрошенную сборку.
P_A>Листинг 23 показывает пример использования этих событий. Главный модуль MainClass использует две сборки: ClassLibrary1, содержащую класс Class1 и ClassLibrary2, содержащую класс Class2. Главный модуль не имеет ссылки на первую сборку, поэтому при попытке найти тип Class1 будет вызываться обработчик TypeResolve, в котором мы загрузим нужную сборку самостоятельно. На вторую сборку ссылка имеется, но у нее выставлен тип CopyLocal=False, поэтому система не сможет определить местонахождение сборки и вызовет обработчик AssemblyResolve, в котором мы загрузим эту сборку самостоятельно.

спасибо большое!!

я пробовал
Assembly my = Assembly.GetEntryAssembly();
my.ModuleResolve += new ResolveEventHandler(ModuleResolve);
но оно не зажишалось. теперь понятно почему!
Re[2]: Проблема с референсами
От: stump http://stump-workshop.blogspot.com/
Дата: 05.04.07 11:02
Оценка: 4 (1)
Здравствуйте, Pavel_Agurov, Вы писали:

P_A>здесь
Автор(ы): Павел Агуров
Издательство: БХВ-Петербург
Цена: 292р.

При написании программ особенно важно не тратить время на поиск стандартных решений, а сосредоточиться на решении конкретной задачи, используя готовый эффективный код, разработанный и проверенный коллегой-программистом. В этой книге собраны лучшие


P_A>55. Перехват загрузки типов и модулей


Все можно сделать гораздо проще, не написам ни одной строчки кода.

<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <probing privatePath="bin;bin2\subbin;bin3"/>
      </assemblyBinding>
   </runtime>
</configuration>
Понедельник начинается в субботу
Re: Проблема с референсами
От: OrSol  
Дата: 05.04.07 11:13
Оценка:
Здравствуйте, abatishchev, Вы писали:
A>Вопрос: как указать приложению дополнительный путь для поиска указанных в референсе библиотек?

Добавить в конфиг файл

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="Plugins" />
    </assemblyBinding>
  </runtime>
</configuration>
<< RSDN@Home 1.2.0 alpha rev. 655>>
Re[2]: Проблема с референсами
От: abatishchev Россия http://godfather.net.ru
Дата: 05.04.07 11:20
Оценка:
OS>Добавить в конфиг файл

OS>
OS><configuration>
OS>  <runtime>
OS>    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
OS>      <probing privatePath="Plugins" />
OS>    </assemblyBinding>
OS>  </runtime>
OS></configuration>
OS>


спасибо! буду знать. я читал в MSDN'е про probing, но ничего не понял, больно сумбурно, на мой взгляд, там это описано..

+ в моём случае решение проблемы кодом, мне кажется, больше подходит, т.к. у меня не WinApp, у которого все пути практически фиксированы, и в конфиг можно дописать, к примеру, /plugins
а библитека-диспетчер модулей для очень гибкого ядра CMS. там всё столь динамично настраивается, что конфиг, боюсь, не подойдёт.
Re[3]: Проблема с референсами
От: efim Россия  
Дата: 05.04.07 21:39
Оценка:
Здравствуйте, stump, Вы писали:

S>Здравствуйте, Pavel_Agurov, Вы писали:


P_A>>здесь
Автор(ы): Павел Агуров
Издательство: БХВ-Петербург
Цена: 292р.

При написании программ особенно важно не тратить время на поиск стандартных решений, а сосредоточиться на решении конкретной задачи, используя готовый эффективный код, разработанный и проверенный коллегой-программистом. В этой книге собраны лучшие


P_A>>55. Перехват загрузки типов и модулей


S>Все можно сделать гораздо проще, не написам ни одной строчки кода.


S>
S><configuration>
S>   <runtime>
S>      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
S>         <probing privatePath="bin;bin2\subbin;bin3"/>
S>      </assemblyBinding>
S>   </runtime>
S></configuration>
S>

Проще, но не совсем. В probing можно указывать только поддиректории относительно base directory
Другие папки указать нельзя
Re[3]: Проблема с референсами
От: stump http://stump-workshop.blogspot.com/
Дата: 06.04.07 05:29
Оценка:
Здравствуйте, abatishchev, Вы писали:

A>а библитека-диспетчер модулей для очень гибкого ядра CMS. там всё столь динамично настраивается, что конфиг, боюсь, не подойдёт.


Трудно представить приложение для которого не подойдет конфиг...
Хочу обратить внимание на один момент. Корень проблемы кроется в том, что модуль-пагин тянет за собой рефренсы на какие-то третьи сборки. Это проблема архитектуры. Подключаемые модули обычно выполняются как реализация интерфейсов, объявленных в базовой системе. Поэтому в них достаточно ссылок на сборки базовой системы и общие сборки .Net. Если же модуль тянет за собой дюжину других сборок то это уже не плагин, и для его реализации нужно использовать другие подходы. Например "Реестр сервисов" — "Провайдер сервиса" как это принято в SOA.
Понедельник начинается в субботу
Re[4]: Проблема с референсами
От: abatishchev Россия http://godfather.net.ru
Дата: 06.04.07 09:03
Оценка:
Здравствуйте, stump, Вы писали:

S>Трудно представить приложение для которого не подойдет конфиг...

S>Хочу обратить внимание на один момент. Корень проблемы кроется в том, что модуль-пагин тянет за собой рефренсы на какие-то третьи сборки. Это проблема архитектуры. Подключаемые модули обычно выполняются как реализация интерфейсов, объявленных в базовой системе. Поэтому в них достаточно ссылок на сборки базовой системы и общие сборки .Net. Если же модуль тянет за собой дюжину других сборок то это уже не плагин, и для его реализации нужно использовать другие подходы. Например "Реестр сервисов" — "Провайдер сервиса" как это принято в SOA.

не обязательно, что модуль-плагин тянет дюжину референсов! хотя бы 1. к примеру, SSL- или JPEG-библиотеку, что угодно! получается, что плагин должен содержать только собственноручно писанный код, и ничего более. хорошо если есть такая возможность. а если нужно хоть что-то зацепить извне — вся архитектура рушится.. а это полная Ж.

а про Реестр-провайдер, спасибо, почитаю!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.