Partager via


C# 3.0 and CodeDOM

The CodeDOM is a very handy .NET API which allows you to programatically compile code using the .NET compilers and programatically construct code without just pasting together strings. 

With the new version of the language, we've heard a numer of questions about how to use the CodeDOM with the new compiler.

There are two aspects to the inegration of C#3.0 with CodeDOM:

  • Programatically compiling C# source code: This is supported in .NET3.5.  The existing CodeDOM is augmented with an overload of CSharpCodeProvider which takes a "providerOptions" argument.  This can be used to point CodeDOM at the new .NET Framework 3.5 C# compiler (which supports C#3.0), by passing a "providerOptions" dictionary containing "CompilerVersion" as "v3.5".  This can also be controlled via the .config file, which is done  for example in Orcas ASP.NET websites targeting .NET3.5. 

  • Programatically constructing C#3.0 source code:  There won't be support for the this in the .NET Framework 3.5 CodeDOM that ships with Orcas.  Luckily, very few of the C# 3.0 features need CodeDOM support - since most new features are expressions, and the CodeDOM doesn't go down to the expression level. 

Example of programatically compiling C#3.0 source code:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
class Program
{
    static void Main(string[] args)
    {
        var csc = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } });
        var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" }, "foo.exe", true);
        parameters.GenerateExecutable = true;
        CompilerResults results = csc.CompileAssemblyFromSource(parameters,
        @"using System.Linq;
class Program {
public static void Main(string[] args) {
var q = from i in Enumerable.Rnge(1,100)
where i % 2 == 0
select i;
}
}");
        results.Errors.Cast<CompilerError>().ToList().ForEach(error => Console.WriteLine(error.ErrorText));
    }
}

Comments

  • Anonymous
    August 08, 2007
    I start a POC of a compiler for C# 3.0 extended (with CodeDom). I want to do a lot of things (http://blog.developpez.com/index.php?blog=121&title=mmcs31&more=1&c=1&tb=1&pb=1) but I only start. You can find my project in codeplex (http://www.codeplex.com/mmcs31).

  • Anonymous
    August 10, 2007
    The comment has been removed

  • Anonymous
    August 12, 2007
    There are several good new blogs from members of the Microsoft C# team. Nevertheless, the most important

  • Anonymous
    December 05, 2007
    Thank you very much, using the alternative of specifying CompilerVersion with value v3.5 on the referred class constructor worked very well. Unfortunately, the other alternative is needed for another application and specifying the same data on its application config file does not work the same. In order to paste the exact config section, I copied it from a just created Visual Studio 2008 ASP.NET Web site’s web.config file: <system.codedom>  <compilers>    <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4"                  type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">          <providerOption name="CompilerVersion" value="v3.5"/>          <providerOption name="WarnAsError" value="false"/>    </compiler>    <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4"                  type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">          <providerOption name="CompilerVersion" value="v3.5"/>          <providerOption name="OptionInfer" value="true"/>          <providerOption name="WarnAsError" value="false"/>    </compiler>  </compilers> </system.codedom> I tried also with the sample on Compiler and Language Provider Settings Schema <providerOption> Element (no difference): <system.codedom>  <compilers>    <!-- zero or more compiler elements -->    <compiler      language="c#;cs;csharp"      extension=".cs"      type="Microsoft.CSharp.CSharpCodeProvider, System,        Version=2.0.3600.0, Culture=neutral,        PublicKeyToken=b77a5c561934e089"      compilerOptions="/optimize"      warningLevel="1" />        <providerOption          name="CompilerVersion"          value="3.5" />  </compilers> </system.codedom> What I am missing? Thank you very much in advance for your help.

  • Anonymous
    December 06, 2007
    Marco - To pick up the .config settings for CodeDOM, you need to create your CodeDOM provider via: var csc = CodeDomProvider.CreateProvider("csharp"); instead of the method used above which directly creates a CSharpCodeProvider.

  • Anonymous
    March 12, 2008
    THANKS ! You saved me after 3 days of looking for what's going wrong ! If you don't use specific version 3.5 for compiler, System.Core.dll causes many difficulties and compilation failed ! thx so much !

  • Anonymous
    June 17, 2008
    The comment has been removed

  • Anonymous
    September 19, 2008
    Echoing what Dude76 said, have been trying this all day. Was missing the compiler version (my error was saying 'From' undefined, just in case someone else has same error). Thanks!

  • Anonymous
    October 20, 2008
    Thanks Luke - this tip saved my bacon!

  • Anonymous
    January 06, 2009
    A few years ago I found myself spending a lot of time writing batch files to perform a variety of relatively

  • Anonymous
    July 24, 2009
    Wow, I was searching for hours how I can use collection initializers in code dom. Thank you so much!