Using reflection for gen code?

I am writing a console tool for creating C # code for objects in a class library. The best / easiest way I can generate code is to use reflection after the library has been built. It works great, but at best it seems random. Since the generated code will be compiled with the library, after making the changes, I will need to build the solution twice to get the final result, etc. Some of these problems could be mitigated with a build script, but it still feels somehow too much for me.

My question is, are there any high level best practices for this kind of thing?

+4
source share
5 answers

Have you considered using T4 templates to generate code? It seems that now he receives much more advertising and attention and more supports VS2010.

This tutorial seems to be database oriented, but it can give you some pointers: http://www.olegsych.com/2008/09/t4-tutorial-creatating-your-first-code-generator/ Also, a recent one appeared here Hanselminutes on T4: http://www.hanselminutes.com/default.aspx?showID=170 .

Edit: Another great place is the T4 tag here on StackOverflow: fooobar.com/questions/tagged / ...

EDIT: (Kiskus, new developments)

Like VS2012, T4 now supports reflection on an active project in one step. This means that you can make changes to your code, and the compiled output of the T4 template will display the latest version, without requiring the second display / assembly step. With this opportunity, I mark this as an accepted answer.

+1
source

Its pretty unclear what you are doing, but it is clear that you have baseline code and based on some of its properties you want to create more code.

So, the key issue here, given the baseline code, how do you extract interesting properties and how do you generate code from these properties?

Reflection is a way of retrieving the properties of an executable code (well, at least, loaded) into the same runtime as the reflection user code. The problem with reflection is that it provides only a very limited set of properties, usually a list of classes, methods, or possibly argument names. IF all the code generation you want to do can be done with just that, well, then the reflection seems just fine. But if you want more detailed information about the code, reflection will not shorten it.

In fact, the only artifact from which truly arbitrary code properties can be extracted is the source code as a character string (how else could you answer, is the number of characters between the add and T operator in the middle of the variable name is a prime number?). As a practical matter, the properties that you can get from characters are usually not very useful (see the Example I just gave :).

The compiler guys have spent the past 60 years figuring out how to extract the interesting features of the program, and you would be a complete idiot to ignore what they have learned over this half century.

They are designed for several relatively standard "compiler data structures": abstract syntax trees (AST), character tables (ST), control flow diagrams (CFG), data flow facts (DFF), triples of programs, ponter analysis, etc. If you want to analyze or generate code, it is best to first process it in such standard compiler data structures and then do the job. If you have AST, you can answer all questions about which operators and operands are used. If you have an ST, you can answer questions about where, where, visible, and some type. If you have CFG, you can answer questions about this β€œbefore”, β€œwhat conditions operator X depends on”. If you have DFF, you can determine which assignments affect actions at a point in the code. Reflection will never provide this IMHO, because it will always be limited by what runtime developers are willing to support when the program starts. (Perhaps someday they will store all the data structures of the compiler, but then this will not be a reflection, it will most likely be compiler support).

Now that you have identified the properties you are interested in, what do you do to generate the code? Here, the compiler guys were so focused on generating machine code that they did not offer standard answers. The guys who make this community are software conversion programs ( http://en.wikipedia.org/wiki/Program_transformation ). The idea here is to preserve at least one representation of your program as an AST and provide special support for matching the syntax of the source code (by creating an AST with a matching pattern from the code fragments of interest) and provide "rewrite" rules that say " when you see this template, then replace it with this template under this condition. " By connecting the condition to various mechanisms for extracting resources from compilers, you will get a relatively simple way to say what you want to get from this 50-year experience. Such program conversion systems have the ability to read in source code, analyze and convert, and typically recover code after conversion.

For your code generation task, you need to read the baseline code in the AST, apply analyzes to determine the properties of interesting ones, use transformations to generate new ASTs, and then spit out the answer.

For such a system to be useful, it should also be able to analyze and print a large number of language source code codes so that people, except C # lovers, can also take advantage of the code analysis and generation.

These ideas are all described in the DMS Software Reengineering Toolkit . DMS handles C, C ++, C #, Java, COBOL, JavaScript, PHP, Verilog, ... and many other languages.

(I am a DMS architect, so I have a pretty biased opinion. YMMV).

+2
source

You can use CodeDom , so you only need to create one.

First, I would read this CodeProject article to make sure there are no language-specific functions that you could not support without using Reflection.

+1
source

From what I understand, you can use something like Common Compiler Infrastructure ( http://ccimetadata.codeplex.com/ ) to programmatically analyze an existing C # source.

This looks pretty attractive to me, although CCI apparently only has full C # language support. A better strategy might be to optimize your existing method.

0
source

I'm not sure how to do this, but you can do it

  • As a step after assembly on your base DLL, run the code generator
  • As another step after build, run csc or msbuild to create the created dll

  • Other things that depend on the generated dll will also have to depend on the underlying dll, so the build order remains correct.

0
source

All Articles