How can we get the T4 template to generate code based on a .cs file that the user is editing? - visual-studio

I'm trying to create a T4 template that will save our developers from creating a lot of boilerplate code that's necessary in our framework. Let's say the developer creates an interface and marks it with our custom attribute. I would like it so that any interface marked with that custom attribute is enhanced by additional methods, which means my T4 template would have to generate partial classes on the fly. However, I would like it so that this automatic generation happens on the fly and seamlessly, preferably when the internal automatic compilation that's used for intellisense happens. You know how when you create a new class in Visual Studio and you switch to another source file and start using that class you didn't have to save or compile it, Intellisense was able to see the new class you created right away? I'd like the same automatic behavior with the code generated from my T4 template. Any thoughts?

You cannot do what you want to do easily, but here are some options ordered from easiest to most likely what you want (hardest).
Create code
snippets
Create a Visual Studio Item Template
Use Castle DynamicProxy to create the extra bits at run time.
Create a separate project to hold the T4 generated classes as described in my answer here
As a pre-step to your project build (modify .csproj file to do this), you can compile the source code from which you want to generated code and then reflect on that, generate the code and then add it to the project before the real compile step. This is what the MSR Orleans project does. You can read their source code here. This is really cool! :-)

Related

Dynamic DbContext Generation

I need to write a web site content management system that makes use of dynamic Entity Framework DbContext generation. As an input I get a custom data types declaration (in xml) that my C# code knows how to parse. On the output, I need to obtain the code for the DbContext that would provide a facility to store the provided data type instances as DbSet's in a database.
I can see there is .tt -> .cs Generator in a form of a plugin for Visual Studio. I can surely create code that would generate an xml-based (I assume it is) .tt template from my custom declaration and then generate a .cs DbContext for this .tt. But how do I run .tt->.cs conversion manually from code?
Usually T4 templates are transformed at design time inside Visual Studio. If you want to use a T4 template at runtime, change the value of the "Custom Tool" property of the .tt's Project item to "TextTemplatingFilePreprocessor".
This will make Visual Studio create a C# class from your T4 template that can be instantiated at runtime, where you can pass parameters to it (e.g. your xml type declaration). Calling the "TransformText()" will return the actual output code of the T4 template containing the data classes.
In order to use those classes at runtime, too, you would need to compile the output code in memory.

How do I modify the template that reference.cs is generated from?

I've been searching on the web for this, and maybe I'm just using the wrong keywords or something? I could use some help.
My problem is simple - we have a bunch of reference.cs files in our solution, which were auto-generated by VS2010 when adding services. These files don't add XML comments by default, so when we build the project, I get 800 or so messages in the build list. This doesn't break anything, but it does make the build take (significantly) longer, and mucks up the output screen.
I "fixed" this by adding the appropriate #pragma statments to the beginning and end of each reference.cs file, but if those ever get regenerated, they will have to be re-added by hand. I'd like to streamline that process and just add them to whatever T4 template VS2010 is using in the first place. The problem is, I don't know where that is, or if VS2010 is using something else to build these files?
Can this be done? Is there a better solution? I don't necessarily want to turn off XML comments for the entire project.
Visual Studio does not use T4 templates to generate the service reference proxy classes (Reference.cs). Instead Visual Studio is most likely using the WsdlImporter and ServiceContractGenerator classes to generate this code.
There is a stackoverflow post on using either a custom wsdl exporter or WCFExtras to add xml comments to the generated code. Both of these assume you have access to the code for the services you are referencing.

Creating a data driven resource manager while keeping the VS2010 designer features

I'm quite used to consume resx designer generated classes, for a clean coding and to avoid mistakes.
However, in a specific project, I need to rely to a database table, containing all labels and their translations in several languages.
I could simply create my own class and get the translated label, however I'd also like to take advantage of VS2010 resource manager and autogenerated *.Designer.cs classes.
I didn't figure out how to do that.
The *.Designer.cs file contains the following comment:
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
So, I suppose I must use the StronglyTypedResourceBuilder (or my own version of this class).
But how to automatically build the class during the design?
And how to save/retrieve data from the DB?

Two Custom tool s for a single file?

I want to generate some code from my dbml(Linq to Sql) file,the dbml file is placed in many part of my project So I wrote a custom tool for this purpose
But the problem is that dbml already has contained MSLinqToSQLGenerator custom tool ,
So do you know any way to set two custom tools for one file, If no, Let me know your idea about that
Visual Studio will only support a single "Custom Tool" per file, but you can add a pre-compilation step to run other tools against anything you want. For instance, I have the following pre-compile step set on the "Build Events" tab of one of my projects.
"$(DevEnvDir)..\..\..\Common Files\Microsoft Shared\TextTemplating\10.0\TextTransform" "$(ProjectDir)DataContext\Northwind.proxy.tt"
There's a lot of relative pathing going on here in order to find the T4 command-line tool, but you get the idea. This particular T4 file counts on being in the same directory as the .dbml file that it reads to generate its output.
Before the project is compiled, you can run whatever external tool you want. Just make sure that after the first run, you include the tool's output in the project. After that, since the file gets changed as part of a PRE-compile step, it will always be updated in each build.
You'd get proper control on the T4 if you include the LINQ to SQL T4 generator in your template's responsibility.
If I understood properly, you want to keep the default behavior of .dbml generator, but also add your own.
This seemed a bit "old", and I haven't personally used LINQ to SQL for some time, but I did use this as-is replacement of T4 generator, that produced the equivalent of the standard .dbml generator.
https://github.com/damieng/L2ST4
Not sure if that's up to date with VS 2010 version, but you can always compare the standard .dbml generated code and this T4 output and make proper changes to achieve identical outcome.
Of course you can simply have multiple different generators, and simply run them with "Transform All Templates", but based on your question, you'd want the generator to be attached to the file specific custom tool.
You might want to check out (unless its already familiar to you) also T4 Toolbox https://github.com/olegsych/T4Toolbox that adds "T4ScriptFileGenerator" custom tool to a file. It effectively runs the T4 code when the file changes.

Software To Help Me Reuse Code

I often find myself writing small (5-20 lines) files for things like input validation, reading a URL and so on. In fact, I probably write nearly the same files over and over because I either forget that I've already implemented such functionality in another project or I don't want to have to go searching for that file.
I want to know if there is a way to simply add code to a global repository from an IDE (in my case Visual Studio) and simply extract that code into whatever project I'm working on. It should be able to:
Extract code to a new file or to the currently open file in my IDE.
w.r.t. #1 I want smart defaults based on how I added the code to the repository.
Easy to use UI.
I don't need replacement/substitution of variables.
For instance, if I right click on a file I want to add to the repository then the default extraction operation is to create a new file. If, instead, I highlight some text in the currently open file and commit that, then the default is just to paste the snippet into the currently open file.
I've tried VS's snippet manager a few times, always with disappointment and quick abandonment. My biggest complaint is its interface and complexity required to add new code to it, plus the inability to extract the code to a file versus just inside whatever I have open.
You might want to check out ReSharper's Live Templates.
I don't use them to the extent that you're obviously looking for, but you can definitely create new file-based templates. I use that all the time when I create a new unit testing fixture class - just Add New Item -> From Template -> NUnit Test Fixture, where "NUnit Test Fixture" is one of my defined file templates.
Additionally, all the templates can be assigned a shortcut sequence, so you can auto-replace a given combination of text with a code snippet.
All the template configuration is file based, so you can save them to solutions or global workspaces as well.

Resources