Сборка не может найти ссылочную сборку при составлении в память с помощью CodedomProvider
-
25-10-2019 - |
Вопрос
Я пытаюсь скомпилировать код в память во время выполнения с помощью CodedomProvider.
Код, который я составляю, имеет ссылку на внешнюю сборку, которую я включаю в параметры, используемые при составлении кода.
Когда я компилируюсь в память и пытаюсь использовать отражение на сборке, сгенерированной в добавлении Visual Studio, это бросает исключение, говоря, что не может найти ссылочную сборку.
(Исключение)
«Невозможно загрузить один или несколько запрашиваемых типов. Получить свойство LoadErexCeptions для получения дополнительной информации».
(LoaderException)
"{" Не удалось загрузить файл или сборку 'Dynamo.jiss.task, версия = 1.0.0.0, культура = нейтральная, publickeytoken = null' или одна из ее зависимостей. Система не может найти указанный файл. ":" Dynamo.jiss.task, версия = 1.0.0.0, культура = нейтральная, publickeytoken = null "}"
Я пытался ссылаться на сборку из разных мест, используя абсолютный путь.
Тот же код работает нормально, если он запускается из приложения консоли, и он также отлично работает в надстройке, если я не компилируюсь в память.
Удаление ссылки на внешнюю сборку и код, который ссылается на него, также работает при составлении памяти, поэтому, вероятно, как описывает исключение, является проблемой с загрузкой ссылочной сборки.
У кого-нибудь есть идея, почему компиляция в память и ссылка на сборку не работает в надстройке?
Есть ли некоторые ограничения в приложении, о котором он работает, или о чем -то, о чем я должен знать? (Мое лучшее предположение в настоящее время)
Должен ли это быть в определенной папке? ссылка на относительный путь? Настройки безопасности? нужно подписано? Любые идеи?
То, что я пытаюсь достичь, - это способ поместить файлы с определенным расширением в проекте и позволить Addin автоматически скомпилировать его и, если он реализует интерфейс itask (от внешней сборки), он вызовет метод setup (), который делает его Возможно, для кода зацепиться в события Visual Studio и выполнять задачи/сценарии, прослушивая различные события. Таким образом, я могу легко выполнить текстовые шаблоны, если изменяется другой файл, или объединять и министерство файлов на разных событиях (сохраненный документ, сборка и т. Д.).
Существует ли что -то подобное (чтобы освободить меня от боли)? :)
Решение
Скорее всего, это происходит потому, что вы говорите Codedom генерировать сборку в памяти (которая действительно является ложью, поскольку он временно генерирует диск, загружает его, затем удаляет файл). Дело в том, что каталог компиляции для сборки Codedom не тот, который вы используете для его компиляции. То есть, если вы работаете в Bin Debug, сборка Codedom генерируется до %temp %.
Вы можете решить это одним из двух способов, которые я могу придумать:
Скомпилируйте сборку Codedom по тому же пути, что и ваша выполняющая сборка.
myCodeProvider.GenerateInMemory = false; // may not be necessary...haven't tried this in a while myCodeProvider.OutputAssembly = string.Format(@"{0}\{1}", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location, "mydll.dll");
Обработайте событие AssemblyResolve и предоставьте сборку Codedom обращаемую ссылку на сборку.
AppDomain.CurrentDomain.AssemblyResolve += OnCurrentDomainAssemblyResolve private static Assembly OnCurrentDomainAssemblyResolve(object sender, ResolveEventArgs args) { // this is absurdly expensive...don't do this more than once, or load the assembly file in a more efficient way // also, if the code you're using to compile the CodeDom assembly doesn't/hasn't used the referenced assembly yet, this won't work // and you should use Assembly.Load(...) foreach (Assembly @assembly in AppDomain.CurrentDomain.GetAssemblies()) { if (@assembly.FullName.Equals(args.Name, StringComparison.OrdinalIgnoreCase)) { return @assembly; } } }