В конце я сделал это почти точно так, как предложил raboof (и похоже на то, что предложил dgvid), за исключением некоторых незначительных изменений и исправленных ошибок. Я выбрал этот метод, потому что он был наиболее близок к тому, что я искал, и не требовал использования сторонних исполняемых файлов и тому подобного. Отлично работает!
Вот как мой код в итоге выглядел:
РЕДАКТИРОВАТЬ: Я решил переместить эту функцию в другую сборку, чтобы я мог повторно использовать ее в нескольких файлах (я просто передаю в Assembly.GetExecutingAssembly ()).
Это обновленная версия, которая позволяет передавать сборку со встроенными dll.
embeddedResourcePrefix - это строковый путь к встроенному ресурсу, обычно это имя сборки, за которой следует любая структура папки, содержащей ресурс (например, «MyComapny.MyProduct.MyAssembly.Resources», если dll находится в папке с именем Resources в проекте). Предполагается также, что DLL имеет расширение .dll.resource.
public static void EnableDynamicLoadingForDlls(Assembly assemblyToLoadFrom, string embeddedResourcePrefix) {
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { // had to add =>
try {
string resName = embeddedResourcePrefix + "." + args.Name.Split(',')[0] + ".dll.resource";
using (Stream input = assemblyToLoadFrom.GetManifestResourceStream(resName)) {
return input != null
? Assembly.Load(StreamToBytes(input))
: null;
}
} catch (Exception ex) {
_log.Error("Error dynamically loading dll: " + args.Name, ex);
return null;
}
}; // Had to add colon
}
private static byte[] StreamToBytes(Stream input) {
int capacity = input.CanSeek ? (int)input.Length : 0;
using (MemoryStream output = new MemoryStream(capacity)) {
int readLength;
byte[] buffer = new byte[4096];
do {
readLength = input.Read(buffer, 0, buffer.Length); // had to change to buffer.Length
output.Write(buffer, 0, readLength);
}
while (readLength != 0);
return output.ToArray();
}
}