Разрешение сборок в Design Automation для Revit

Я использую автоматизацию проектирования для изменения значений параметров семейства на основе данных в файле CSV. Библиотека CSV, которую я использую, зависит от Microsoft.Bcl.AsyncInterfaces v1.0.0.0+, а используемая мной библиотека JSON зависит от Microsoft.Bcl.AsyncInterfaces v7.0.0.0. Я могу включить только одно или другое в свой AppBundle (из-за дублирования имен в одном и том же каталоге), но в любом случае я получаю исключение из среды выполнения DA4R в зависимости от того, что отсутствует:

System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Bcl.AsyncInterfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the file specified.

Моя локальная версия этой надстройки использует файл app.config с перенаправлением привязки для решения этой проблемы, но моя версия DA4R не работает, поскольку не включает этот файл.

На основе этого примера я думаю, что пользовательская функция разрешения сборки будет работать, но я не знаю, как получить доступ к местоположению файлов сборки.

Локальный каталог среды выполнения включает только мои рабочие файлы, а не файлы AppBundle. Я вижу, что эти файлы расположены по адресу T:\Aces\Applications\ffc6436bec04d21d55ea37de192e1fe6.<APPNAME>.<ACTIVITYNAME>[##].package, но по понятным причинам не хочу жестко запрограммировать номер текущей версии в исходном коде.

Я на правильном пути или есть более простой путь?

Чтобы файл действовал, это должен быть файл .exe.config, а это означает, что вам необходимо скопировать acad.exe.config (или любое другое имя .exe) в каталог установки CAD. Не то чтобы это помогало, привязкаRedirect не решает проблему ненайденного файла. Реальная проблема заключается в том, что CLR просто не ищет в каталоге надстройки какие-либо зависимости. Сначала он просматривает GAC, а затем каталог установки CAD. Вы можете использовать событие AppDomain.AssemblyResolve, чтобы помочь.

Hans Passant 19.09.2023 01:36

@blake Ты на правильном пути. Резолвер сборки - это правильно.

Rahul Bhobe 20.09.2023 06:57
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
63
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Да, вы можете получить доступ к файлам AppBundle во время работы WorkItem. Пожалуйста, обратитесь к: https://forge.autodesk.com/blog/handle-command-line-arguments и https://forge.autodesk.com/blog/store-template-documents-appbundle

Мне удалось использовать следующие строки для доступа к моему «дубликату» .dll и правильно его загрузить:

string assemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

string fullPath = assemblyPath + @"\lib\Microsoft.Bcl.AsyncInterfaces.dll";

Assembly myAssembly = Assembly.LoadFrom(fullPath);

Когда и где ты это звонишь? Вы звоните из OnStartup()?

Rahul Bhobe 20.09.2023 07:20

Я вызываю это в своем HandleDesignAutomationReadyEvent().

Blake Hageman 20.09.2023 15:48

Я бы рекомендовал использовать AppDomain.CurrentDomain.AssemblyResolve, чтобы он срабатывал, когда это необходимо. Похоже на блог Джереми , которым вы поделились в своем описании.

Rahul Bhobe 20.09.2023 18:47

Метод разрешения сборок, который вы используете для надстройки рабочего стола, также должен работать в пакете приложений DA.

public ExternalDBApplicationResult OnStartup(Autodesk.Revit.ApplicationServices.ControlledApplication app)
{
    DesignAutomationBridge.DesignAutomationReadyEvent += HandleDesignAutomationReadyEvent;
    AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve;
    return ExternalDBApplicationResult.Succeeded;
}

private static readonly string AssemblyLocation  = Assembly.GetExecutingAssembly().Location;
private static readonly string AssemblyDirectory = Path.GetDirectoryName(AssemblyLocation);
private static string GetPathInAssemblyDirectory(string filename) => Path.Combine(AssemblyDirectory, filename);

private static Assembly AssemblyResolve(object sender, ResolveEventArgs args)
{
   // You could either check for input argument against a hardcoded
   // list of dlls (in your case Microsoft.Bcl.AsyncInterfaces.dll)
   // or like below, check if the dll attempted to be loaded (as
   // per to the input argument is something you bundled.
   string filename = args.Name.Split(',')[0] + ".dll".ToLower();
   string assemblyFilename = GetPathInAssemblyDirectory(filename);
   if (!File.Exists(assemblyFilename))
      return null;

   return Assembly.LoadFrom(assemblyFilename);
}

public void HandleDesignAutomationReadyEvent(object sender, DesignAutomationReadyEventArgs e)
{
   // Your code here...
   // Your code here...
   // Your code here...
   e.Succeeded = true;
}

Примечание. Я оставляю общий ответ выше. Но, глядя на ваш другой ответ, в вашем случае входная dll находится в подпапке lib, поэтому вам придется это учитывать.

Другие вопросы по теме