Search code examples
c#code-generationcodedom

CodeDom not using MemberAttributes


When trying to learn CodeDom under Ms visual studio, I noticed that the code generation seems to ignore the member attributes set for my class.

This is my sample code

using Microsoft.CSharp;
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;

namespace CodeDomTest
{
    class Program
    {
        public static CodeCompileUnit BuildHelloWorldGraph()
        {
            // Create a new CodeCompileUnit to contain
            // the program graph.
            CodeCompileUnit compileUnit = new CodeCompileUnit();

            // Declare a new namespace called Samples.
            CodeNamespace samples = new CodeNamespace("Samples");
            // Add the new namespace to the compile unit.
            compileUnit.Namespaces.Add(samples);

            // Declare a new type called Class1.
            CodeTypeDeclaration class1 = new CodeTypeDeclaration("Class1");
            // Add the new type to the namespace type collection.
            samples.Types.Add(class1); // should be private
            Console.WriteLine("Class1 attributes: " + class1.Attributes);

            return compileUnit;
        }
        public static string GenerateCSharpCode(CodeCompileUnit compileunit)
        {
            // Generate the code with the C# code provider.
            CSharpCodeProvider provider = new CSharpCodeProvider();

            // Create a TextWriter to a StreamWriter to the output file.
            StringWriter strWriter = new StringWriter();

            IndentedTextWriter tw = new IndentedTextWriter(strWriter, "    ");

            // Generate source code using the code provider.
            provider.GenerateCodeFromCompileUnit(compileunit, tw,
                new CodeGeneratorOptions());

            // Close the output file.
            tw.Close();

            return strWriter.ToString();
        }

        static void Main(string[] args)
        {
            Console.WriteLine(GenerateCSharpCode(BuildHelloWorldGraph()));
            Console.ReadKey();
        }
    }
}

It produces the following output:

Class1 attributes: 20482
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Samples {


    public class Class1 {
    }
}

As you can see, the Attributes for the class1 object are set to 20482, which is the default value. As described here, this means the class should be private(20480) and final(2). Instead the class is generated as public. What is happening here?


Solution

  • From a flick through the docs:

    The TypeAttributes property indicates the TypeAttributes values for the type declaration, which indicate the type category of the type.

    Looking further at TypeAttributes:

    The Attributes property is a side effect of the CodeTypeDeclaration class inheriting from CodeTypeMember so that classes can be nested. The flags in the TypeAttributes property should be used instead of the flags in the Attributes property.

    (Emphasis mine).

    So it looks like you should be applying TypeAttributes.Sealed, etc.

    Also note that "private" only applies to nested classes (and members), while "final" normally refers to members: "sealed" is the term for classes.