1

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" } })
webworm
  • 10,587
  • 33
  • 120
  • 217
  • Extension methods were added in c# 3.5. What happens if you explicitly target a compiler version later than that? See [What happens if I don't specify CompilerVersion with CSharpCodeProvider and why do most samples specify it?](https://stackoverflow.com/q/19400394) and [How can I target a specific language version using CodeDOM?](https://stackoverflow.com/q/20018979). – dbc Feb 16 '18 at 19:41
  • I am not sure what happens as I am not specifying the target framework (perhaps that is the issue?). I will try and add this and also change the machine.config and web.config. Thank you for the links! – webworm Feb 16 '18 at 20:10
  • I ran a script that contained Environment.Version and I got back `4.0.30319.34209`. I was hoping this might be the answer, but I guess not. From what I have looked up this means the environment is `.NET v4.5.2` – webworm Feb 16 '18 at 22:30

1 Answers1

4

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.

webworm
  • 10,587
  • 33
  • 120
  • 217