Сбой генерации кода CodeDomProvider с определенным синтаксисом Linq - PullRequest
4 голосов
/ 07 марта 2012

Я использую 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 ]

3 голосов
/ 27 мая 2012

Мне кажется, это работает:

    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();
    }
0 голосов
/ 08 марта 2012

Я не нашел ответа на вопрос, как получить достоверную информацию об исключениях, однако я решил эту проблему.Библиотека классов, которая содержала код компилятора выше, была установлена ​​в AnyCpu, но контекст, в котором она работала в ASP.Net, был x86.Так что это приводило к сбою при попытке загрузить System.dll, так как он загружал неправильную версию (или что-то глупое).

Я буду рад поставить кому-то еще галочку ответа, если вы сможете (а) выяснить, как получить реальное сообщение об ошибке или (б) загрузить правильный тип ссылки.

0 голосов
/ 08 марта 2012

Вы, вероятно, получаете 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(). Ошибка компиляции не вызывает исключение, вы должны вручную проверить ошибки компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...