Ссылка на встроенные сборки из динамически создаваемых классов - PullRequest
1 голос
/ 11 июня 2011

Я использую технику встраивания dll (встроенного ресурса) в exe и использую следующий код для разрешения неизвестных dll во время выполнения.

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    String resourceName = "Project.lib." + new AssemblyName(args.Name).Name + ".dll";

    using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
    {
        Byte[] assemblyData = new Byte[stream.Length];
        stream.Read(assemblyData, 0, assemblyData.Length);
        return Assembly.Load(assemblyData);
    }
};

Однако, когда я встраиваю dll Spark View Engine (например), он падает. Но только в одном конкретном месте. Сама Spark динамически генерирует классы на лету. Затем эти классы ссылаются на Spark (using Spark и т. Д.). Именно в этот момент я получаю следующую ошибку.

Тип 'Spark.Class' определен в сборка, на которую нет ссылок. Вы должны добавить ссылку на сборка "Искра"

Я почти уверен, что это не имеет ничего общего с движком представления Spark, но связано со ссылкой на встроенную сборку из динамически генерируемого класса.

Обновление: трассировка стека

Исключительная ситуация возникла при запуске Сообщение о задачах проекта: Spark.Compiler.BatchCompilerException: Компиляция динамического представления не удалась. C: \ Users \ Adam \ AppData \ Local \ Temp \ kdsjyhvu.0.cs (6,14): ошибка CS0012: тип 'Spark.AbstractSparkView' определен в сборке, на которую нет ссылок. Вы должны добавить ссылку на сборку Spark, версия = 1.5.0.0, Culture = нейтрально, PublicKeyToken = 7f8549eed921a12c 'в Spark.Compiler.BatchCompiler.Compile (Boolean отладка, String languageOrExtension, String [] sourceCode) в Spark.Compiler.CSharp.CSharpViewCompiler.CompileView (IEnumerable 1 viewTemplates, IEnumerable 1 все ресурсы) в Spark.SparkViewEngine.CreateEntryInternal (SparkViewDescriptor дескриптор, логическая компиляция) в Spark.SparkViewEngine.CreateEntry (SparkViewDescriptor дескриптор) в Spark.SparkViewEngine.CreateInstance (SparkViewDescriptor дескриптор) в ProjectTasks.Core.Templater.Populate (String templateFilePath, Данные объекта) в \ ProjectTasks \ Основные \ Templater.cs: линия 33 в ProjectTasks..Core.EmailTemplates.RenderImpl (String имя, данные объекта) в \ ProjectTasks \ Основные \ EmailTemplates.cs: линия 19 в ProjectTasks.Tasks.EmailUsersWithIncompleteModules.Run () в \ ProjectTasks \ Tasks \ EmailUsersWithIncompleteModules.cs: линия 41 в ProjectTasks.MaintenanceTaskRunner.Run (Boolean runNow, IMaintenanceTask [] tasks) в \ ProjectTasks \ MaintenanceTaskRunner.cs: линия 25 в ProjectTasks.Initialiser.Init (String [] args) в \ ProjectTasks \ Initialiser.cs: линия 30

У кого-нибудь есть идеи по поводу резолюции, если она вообще есть?

Ответы [ 3 ]

2 голосов
/ 12 июня 2011

Полагаю, Spark использует CodeDom для динамической генерации кода.CSharpCodeProvider внутренне генерирует исходный код и запускает csc.exe для получения новых типов.Поскольку csc.exe нужны физические файлы в качестве ссылок, трюк AssemblyResolve в этом случае не поможет.

1 голос
/ 12 июня 2011

Трассировка стека настоятельно предполагает, что Spark использует System.CodeDom для динамического создания сборок.Это требует, чтобы ссылочные сборки были файлами на диске, компилятор C # работает вне процесса.Обычно это не проблема, потому что у вас есть Spark.dll в том же каталоге, что и ваш EXE.

Вы не можете сделать эту работу.

Примечание: этот метод ужасно растрачивает системные ресурсы,Вы удваиваете объем памяти, необходимый для сборок.Это также дорогой вид памяти, он не может быть разделен между процессами и поддерживается файлом подкачки вместо файла сборки.Вы также можете купить себе серьезные проблемы с типом личности..NET уже поддерживает развертывание в одном файле.Это называется setup.exe

0 голосов
/ 13 июня 2011

Как уже говорили другие, проблема заключается в том факте, что CodeDom создает артефакты на диске, к которому затем впоследствии требуется доступ для визуализации представлений.

Помимо того, что встраивание Spark в любом случае является потенциальной проблемой с памятью, я считаю, что есть потенциальное решение этой проблемы. Учитывая тот факт, что проблема вызвана динамической генерацией представлений на лету, почему бы не воспользоваться опцией пакетной компиляции Spark , чтобы сгенерировать dll для ваших представлений как часть вашей сборки.

Вы можете использовать код, подобный следующему, для достижения этой цели:

var factory = new SparkViewFactory(settings)
               {
                   ViewFolder = new FileSystemViewFolder(viewsLocation)
               };

// And generate all of the known view/master templates into the target assembly
var batch = new SparkBatchDescriptor(targetPath);

factory.Precompile(batch);

В конце концов, у вас должна быть выходная dll, которая будет содержать скомпилированные представления, и затем вы можете встраивать эту dll так же, как вы встраиваете основной Spark.dll.

Надеюсь, это поможет
Rob

...