webworm
webworm

Reputation: 11019

LINQ Extensions not available inside CSharpCodeProvider

I have a .NET application that can take a script written in C# and executes it internally. The scripts are parsed by the class listed below and then compiled. I find that whenever I try and use System.Xml.Linq in the C# script that is compiled I get a compile error and I am not sure why.

public static void CreateFunction(string scriptCode, BO.ObjectBO obj)
{
    CSharpCodeProvider provider = new CSharpCodeProvider();
    CompilerParameters options = new CompilerParameters();
    options.ReferencedAssemblies.Add("System.Data.dll");
    options.ReferencedAssemblies.Add("System.dll");
    options.ReferencedAssemblies.Add("System.Xml.dll");
    options.ReferencedAssemblies.Add("System.Linq.dll");
    options.ReferencedAssemblies.Add("System.Xml.Linq.dll");

    options.GenerateExecutable = false;
    options.GenerateInMemory = true;
    CompilerResults results = provider.CompileAssemblyFromSource(options, scriptCode);

    _errors = results.Errors;

    if (results.Errors.HasErrors)
    {
        DataTable errorTable = BO.DataTableBO.ErrorTable();
        foreach(CompilerError err in results.Errors)
        {
           DataRow dr = errorTable.NewRow();
           dr["ErrorMessage"] = "Line "+ err.ErrorNumber.ToString() + " " + err.ErrorText;
           errorTable.Rows.Add(dr);
         }
        return;
    }

    Type binaryFunction = results.CompiledAssembly.GetType("UserFunctions.BinaryFunction");

    _methodInfo = binaryFunction.GetMethod("Function");
}

Here is the error message I get when I try and run a script that makes use of LINQ extensions inside the compiler.

'System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>' does not contain a definition for 'Select' and no extension method 'Select' accepting a first argument of type 'System.Collections.Generic.IEnumerable<System.Xml.Linq.XElement>' could be found (are you missing a using directive or an assembly reference?)

Does anyone see what I may be doing wrong? I am attempting to include System.Linq and System.Xml.Linq yet the compiler does not seem to be able to locate them.

Here is an example C# script I am trying to compile that makes use of LINQ extensions.

using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Xml.Linq;

namespace CompilerTest
{
  public class BinaryFunction
  {
    public static void Function()
    {
      string xmlData = @"<data>
                          <clients>
                            <client>
                              <clientId>1</clientId>
                              <clientName>Dell</clientName>
                            </client>
                            <client>
                              <clientId>2</clientId>
                              <clientName>Apple</clientName>
                            </client>
                          </clients>
                        </data>";

      XDocument xDoc = XDocument.Parse(xmlData);

      List<string> results = xDoc.Descendants("data")
                            .Descendants("client")
                            .Select(x => x.Element("clientName").Value)
                            .ToList<string>();

    }
  }
}

UPDATE: I confirmed that the following assemblies were in the GAC. System.Xml and System.Xml.Linq. I also added the compiler version to the constructor and I still get the same error.

  CSharpCodeProvider(new Dictionary<String, String> { { "CompilerVersion", "v4.6.1" } })

Upvotes: 1

Views: 656

Answers (1)

webworm
webworm

Reputation: 11019

After searching for related errors I found the solution. I needed to add System.Core as a referenced assembly.

options.ReferencedAssemblies.Add("System.Core.dll");

Once I did this then the LINQ assemblies were used and I was able to use LINQ extensions. So to be clear my new code is

CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters options = new CompilerParameters();
options.ReferencedAssemblies.Add("System.Data.dll");
options.ReferencedAssemblies.Add("System.dll");
options.ReferencedAssemblies.Add("System.Xml.dll");
options.ReferencedAssemblies.Add("System.Linq.dll");
options.ReferencedAssemblies.Add("System.Xml.Linq.dll");
options.ReferencedAssemblies.Add("System.Core.dll");

I am not sure why the reference to System.Core.dll is needed to be added as I would assume that it was referenced by default when creating a compiler instance but I guess not.

Upvotes: 4

Related Questions