Is There an Official Replacement for CodeDom?
Asked Answered
D

2

13

I am looking into the System.CodeDom namespace for language-independent (at least within certain bounds) source code generation, and I have found some information discouraging the use of CodeDom.

I think some of the omissions described in this early blogpost have been fixed by now, and the fact that CodeDom does not seem to provide a way to create a switch statement still allows for - less performant? - workarounds without uglifying the public interface of the generated types. The same applies to automatic C# properties and collection initializers.

However, other omissions cannot really be worked around, such as the inability to create finalizers, the impossibility to declare extension methods, or the lacking direct support of generic reference type constraints.

Note that the suggested solutions with CodeSnippetTypeMember or injecting literal source code snippets by any other means are not satisfying as they are not language-independent - thereby removing the whole point of using CodeDom rather than String.Format with literal code snippets.

Lastly, it is even suggested in this SO question that 'CodeDom is a failure and that Expression Trees (or rather "Statement" Trees) are the way forward' - though without any explanation how to actually obtain any source code from an expression tree (beside the restriction that classes cannot be declared with expression trees.

Is CodeDom still the method of choice to have source code generated, or does the current BCL offer any obscure replacement with a name that I did not think of?

Diffusivity answered 10/2, 2013 at 11:2 Comment(5)
https://mcmap.net/q/50276/-microsoft-roslyn-vs-codedomPostorbital
@DavidBrabant (and also at driis, who pointed this out before): Thank you, Roslyn is just one of the software names you cannot possibly find unless you already know them. I will take some time to look into this before selecting an answer referring to this as accepted.Diffusivity
@O.R.Mapper I think the same applies to the names of most technologies in .Net: LINQ, Entity Framework, or CodeDOM.Lysander
Also, your requirements are kind of contradictory: you want something that's language-agnostic, but at the same time supports all language-specific features.Lysander
@svick: It's true that many software names suffer from this, though the ones you named are still rather self-explanatory (in the case of LINQ, at least if you find out what the acronym stands for). Nonetheless, I don't see any contradiction in my requirements: IL code is not contradictory either, just because it can be compiled to from a variety of languages with their special features. And some of the "special features" are just the only way of writing certain code elements in some languages, such as the this keyword for extension methods in C#.Diffusivity
O
4

I think CodeDom is still the best solution in the BCL today, but: The Roslyn project is far along and has already launched several CTPs. The goal is to make the compiler available as a service, and it will enable code generation and code inspection scenarios with a simple API.

Take a look at it, if you can use pre-release bits for your project: Roslyn CTP. Here is a related (albeit outdated, still some good info) StackOverflow question: Microsoft Roslyn vs. CodeDom. And finally, an article that talks about using Roslyn for code generation: Code Generation in .NET with the Roslyn CTP

Ogham answered 10/2, 2013 at 11:13 Comment(1)
I wouldn't call the API simple, especially when compared with CodeDOM. For example, to create a simple autoproperty, you need this monstrosity.Lysander
S
3

No. CodeDom is useful to generate code to execute. Its ability to also generate text was merely an accidental by-product, required because compilers need text. If you really care about the text then there are lots of reasons to dislike CodeDom and nothing in the framework to help you.

Other solutions are similarly focused on generating executable code. Reflection.Emit generates IL, the universal language in .NET, but offers no simple way to decompile although any decent decompiler (ILSpy, Reflector, etc) can certainly help. Linq.Expressions is pure executable code and not generally useful to generate complete programs. Roslyn is heavily biased towards already having the text.

Probably the best way forward is to deprecate your requirement for having the text in a specific language. All .NET compilers have the same kind of output, they all compile to IL. Which makes limiting your choices to one language a viable approach. It isn't otherwise clear from your question whether that's a reasonable limitation at all. It does appear to be a common choice, I can't think of a project that ever tried to solve the CodeDom restrictions. The kind of projects available at codeplex.com that target CodeDom instead try to minimize the pain of the verbosity required in code that uses CodeDom.

Septa answered 10/2, 2013 at 11:54 Comment(4)
I'm creating a library that can be configured with Xml files, and while access to everything defined in the Xml files via the library's types is possible with runtime checks, as an extra service I'm providing a tool that automatically creates code for wrapper classes based on the Xml config files. This would add the benefit of compile-time checking the access to stuff defined in the Xml files.Diffusivity
This generator works well for C#, but it would be nice to also support other languages, so projects created in other .NET languages can include their wrapper class source files just as easily as C# projects. Rather than write the generator (that is mostly made up from source code fragments) basically from scratch for each language, defining the wrapper classes just once as an abstract code model and then feeding that to a source code generator for the desired language would seem like a much cleaner solution to me.Diffusivity
Well, there you go. It is much simpler to have these other language projects add a reference to the assembly that CodeDom generates. The metadata in the assembly is language agnostic, any .NET language can consume it.Septa
That sounds like a working solution, but I'm wary of increasing the number of assemblies to reference (especially when the additional assembly contains just a handful of additional classes), as having many assemblies frequently seems to be considered an antipattern (e.g. here, here, or here).Diffusivity

© 2022 - 2024 — McMap. All rights reserved.