views:

354

answers:

5

Is it possible to generate and build some c# code based on the code from the same project. I tried with T4 and Reflection, but there are some assembly locking issues. Is there any other way?

A: 

There is a third party C# .NET variant of JavaCC that we use at work.

Also an interesting article about how to make one: http://msdn.microsoft.com/en-us/magazine/cc136756.aspx

Kave
Is he trying to build a compiler or a code generator?
Robert Harvey
A: 

It really depends on what exactly are you trying to achieve, but on a general case I'd recommend using T4 templates.

And yes, it is possible to use T4 templates inside your project to generate code in your project based on some local settings, but you should define what are you trying to do.

If you want to generate code based on some classes that you define in the same project - this doesn't sound like something easily achievable (after all you want to compile some of the classes in the current project, generate some code based on them and after that generate classes again... umm.. ?)

But if you want to store some settings and then run the T4 template and generate some code based on these settings - this is easily achievable. T4MVC is an example (they generate code based on a settings file that is copied and stored in the project alongside the T4 template). This template also looks at the current files available in the solution, and generates string constants based on each file. That kind of sounds like it would really help you with your problem, whatever it is :)

If you're still unsure - you can specify more details about what you want to do, and we'll try to help you :)

Artiom Chilaru
Thanks for the answer. What I'm trying to achieve is to be able to generate additional code based on classes in my project. Something like CloneEntity(), SerializeEntity() or InvokeSomeMethod. All this code is dependent on class names, members... Generated code can be in another project, but it would be nicer to keep everything together.
Marko
I see.. You'll most likely have to keep these classes in a separate project, as you're trying to generate code on semi-generated entities, and I'm not sure if that's possible. Sounds like if you follow exactly the same approach you were using, but keep these T4s in a separate assembly - it should just work (it doesn't have to be a separate assembly with JUST the T4s of course.. You can have any other kinds of stuff in there, but the T4 should reflect classes in a separate, already compiled assembly :) )Good luck!
Artiom Chilaru
+1  A: 

You can definitely write your own code generator, all in C# - after all, "code" that's being generated is just a text file you write out.

But what's wrong with T4 templates? They offer a lot of functionality that you don't have to reinvent yet again - why not use it? Can you tell us in more detail what problems you're having with T4?

T4 is really just a bunch of classes in .NET, too - so you could definitely write your own code generator handling some of the logic, and use T4 to do the templating & replacing those template values part. But again: in order to help you diagnose your T4 problems, we'd need to know more about those....

marc_s
For example I would like to generate a CloneEntity for my L2S model.I need to read properties and generate Clone method. It can be done with T4 and reflection, but there is that issue about assembly locking. You have to close VS and open it again after every run.
Marko
As for CloneEntity: why not just serialize the entity to a memory stream and deserialize it from there? THat's the standard way of doing it, it's proven its worth, it doesn't require any trickery or code generation....
marc_s
+1  A: 

Reflection works fine for me. You can get around assembly locking issues by isolating your build task to a separate AppDomain within VS. When the task completes, any assemblies you need to use for code generation will be unloaded together with the task's AppDomain. See AppDomainIsolatedTask.

Anton Tykhyy
Not sure if I understand. I should write my own build task which inherits AppDomaniIsolatedTask and starts T4 code generator. Is that it?
Marko
Yes, this way you should be able to work around VS locking your assemblies during builds. As for the actual code generator, use what suits you best — T4 if you like T4.
Anton Tykhyy
+1  A: 

This example from Oleg Sych uses FXCop's introspection engine instead of reflection. That way, the assemblies do not get locked.

Unfortunately, Reflection is optimized for code execution. One particular limitation makes it ill-suited for code generation - an assembly loaded using Reflection can only be unloaded with its AppDomain. Because T4 templates are compiled into .NET assemblies and cached to improve performance of code generation, using Reflection to access the component assembly causes T4 to lock it.

Alternatively, if you're only targeting Linq to SQL classes, you could generate code from the dbml file instead of the code that L2S generates from the dbml. I've got an example of something similar (an edmx file) on my own blog.

Rob Fonseca-Ensor