Генерация Кода CodeDomProvider Завершается Неудачей С Определенным Синтаксисом Linq
Я использую CodeDomProvider для компиляции некоторого кода Linq и динамического выполнения запросов. Однако я столкнулся с очень странной проблемой.
Если мой запрос Linq в сгенерированном коде выглядит так, то все работает:
namespace Dynamic
{
using System.Linq;
using System.Collections.Generic;
public static class Query
{
public static int GetRecords()
{
MyData.Data.DataMart container = new MyData.Data.DataMart();
return (container.EventDetails).Count();
}
}
}
Это компилируется и работает просто отлично. Однако если я изменю запрос linq на следующий, то он не сможет скомпилироваться:
return (from e in container.EventDetails select e).Count();
Это прекрасно работает, если я помещаю это как статический код, но если я пытаюсь скомпилировать его с помощью CodeDomProvider, это не удается (и я не нашел ни одного хорошего метода, чтобы получить сообщения об ошибках о том, почему это не удается). Я хотел бы использовать стиль синтаксиса from-in-select, так как это облегчит мне генерацию запросов linq, но я не могу понять, почему они не компилируются.
Вы можете увидеть часть кода, который я использую для компиляции этого фрагмента, по ссылке в верхней части этого сообщения.
Спасибо!
Редактировать: копирование кода из сообщения, на которое я ссылался:
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CompilerParameters cp = new CompilerParameters();
cp.GenerateInMemory = true;
cp.ReferencedAssemblies.Add("mscorlib.dll");
cp.ReferencedAssemblies.Add("System.dll");
cp.ReferencedAssemblies.Add("System.Core.dll");
cp.ReferencedAssemblies.Add("System.Data.Linq.dll");
cp.ReferencedAssemblies.Add("System.Data.Entity.dll");
cp.ReferencedAssemblies.Add("MyApp.Data.dll");
var results = provider.CompileAssemblyFromSource(cp, source);
var assm = results.CompiledAssembly;
Edit2: Что касается исключение идет, я получаю исключение на предпоследней строке кода (var results = ...). Исключение составляет исключение BadImageFormatException:
Не удалось загрузить файл или сборку '0 байт, загруженных из системы,
Версия=4.0.0.0, культуры=нейтральных, PublicKeyToken=b77a5c561934e089 "или"
одна из его зависимостей. Была предпринята попытка загрузить программу с помощью
неверный формат
3 ответов:
Это, кажется, работает для меня:
static void Main(string[] args) { string sourceCode = @"namespace Dynamic { using System.Linq; using System.Collections.Generic; public static class Query { public static int GetRecords() { MyApp.Data.DataMart container = new MyApp.Data.DataMart(); //return (container.EventDetails).Count(); return (from e in container.EventDetails select e).Count(); } } }"; string sDynamDll = "Dynamic.dll"; string sDynamClass = "Query"; string sDynamMethod = "GetRecords"; System.CodeDom.Compiler.CompilerParameters cp = new CompilerParameters(); cp.GenerateExecutable = false; cp.GenerateInMemory = true; cp.OutputAssembly = sDynamDll; cp.ReferencedAssemblies.Add("mscorlib.dll"); cp.ReferencedAssemblies.Add("System.dll"); cp.ReferencedAssemblies.Add("System.Core.dll"); cp.ReferencedAssemblies.Add("System.Data.Linq.dll"); cp.ReferencedAssemblies.Add("System.Data.Entity.dll"); cp.ReferencedAssemblies.Add("MyApp.Data.dll"); var providerOptions = new Dictionary<string, string>(); providerOptions.Add("CompilerVersion", "v4.0"); CodeDomProvider compiler = CodeDomProvider.CreateProvider("C#", providerOptions); CompilerResults cr = compiler.CompileAssemblyFromSource(cp, sourceCode); if (cr.Errors.HasErrors) { StringBuilder errors = new StringBuilder("Compiler Errors :\r\n"); foreach (CompilerError error in cr.Errors) { errors.AppendFormat("Line {0},{1}\t: {2}\n", error.Line, error.Column, error.ErrorText); } } // verify assembly Assembly theDllAssembly = null; if (cp.GenerateInMemory) theDllAssembly = cr.CompiledAssembly; else theDllAssembly = Assembly.LoadFrom(sDynamDll); Type theClassType = theDllAssembly.GetType(sDynamClass); foreach (Type type in theDllAssembly.GetTypes()) { if (type.IsClass == true) { if (type.FullName.EndsWith("." + sDynamClass)) { theClassType = type; break; } } } // invoke the method if (theClassType != null) { object[] method_args = new object[] { }; Object rslt = theClassType.InvokeMember( sDynamMethod, BindingFlags.Default | BindingFlags.InvokeMethod, null, null, // for static class method_args); Console.WriteLine("Results are: " + rslt.ToString()); } Console.ReadKey(); }
Вы, вероятно, получаете
BadImageFormatException, потому что ваш код на самом деле не компилируется в допустимую сборку. Это может быть связано с тем, что по умолчанию используется старый компилятор 2.0. Проверьте ссылку ниже для включения C# версии 3.5 (я не знаю, поддерживается ли 4.0, но вам это не нужно):Http://blogs.msdn.com/b/lukeh/archive/2007/07/11/c-3-0-and-codedom.aspx
Также проверьте коллекцию
ErrorsнаCompilerResult, которая возвращается из методаCompileAssemblyFromSource(). Отказ от компиляции не делает чтобы создать исключение, необходимо вручную проверить наличие ошибок компиляции.
Я не нашел ответа, Как получить хорошую информацию об исключениях, однако я решил эту проблему. Библиотека классов, содержащая приведенный выше код компилятора, была установлена в значение AnyCpu, но контекст, в котором она выполнялась ASP.Net был х86. Так что это было причиной его сбоя, когда он пытался загрузить систему.dll, так как он загружал неправильную версию (или что-то глупое вроде этого).
Я буду счастлив дать кому-то другой ответ галочкой, если вы можете (а) выяснить, как получить реальную ошибку сообщение от этого или (b) загрузить правильный тип ссылки.
Comments