All is good until you realize the following: You cannot recompile the library after a T4 template that uses it has been run in Visual Studio until you close that instance of VS. What a bummer - that destroys the tight edit->run template->edit cycle.
The solution: A directive processor that creates a temporary copy of the referenced assembly and loads that copy for the template generation. Each time the assembly changes, a new copy is created and the new copy is loaded for the next template generation (the templating AppDomain has to be force-unloaded to make this work). The copies are lazily cleaned up when they become unused.
I've added such a directive processor to the T4Toolbox project at codeplex. You can use it as follows:
<#@ VolatileAssembly processor="T4Toolbox.VolatileAssemblyProcessor" name="CodeGenerationLibrary.dll" #>
You should then add a reference to CodeGenerationLibrary from the project that contains the T4 template and set CopyLocal=true. If you cannot set a project reference, you can of course provide the relative path to the CodeGeneration.dll and ensure that it is built before code-gen happens.
If you don't want to get the entire T4Toolbox project, the code (with some names different from the T4Toolbox version) is pasted in the DSL Tools forum here.
Hi Oleg,
ReplyDeleteI posted a patch on CodePlex which make the VolatileAssemblyProcessor use the ResolveAssemblyReference instead of the ResolvePath method on the Host class. This allows us to use VS macro in the path ($SolutionDir$, etc.).
I use it on my projects and it works like a charm :)
Does this work with VS2010 RC1? I'm getting the following exception thrown after following the above instructions.
ReplyDeleteAn Exception was thrown while processing a directive named 'VolatileAssembly'. The transformation will not be run. The following Exception was thrown:
System.TypeLoadException: Could not load type 'Microsoft.VisualStudio.TextTemplating.Interfaces.ITextTemplatingEngineHost' from assembly 'Microsoft.VisualStudio.TextTemplating.Interfaces.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
at T4Toolbox.VolatileAssemblyProcessor.ProcessDirective(String directiveName, IDictionary`2 arguments)
at Microsoft.VisualStudio.TextTemplating.Engine.ProcessCustomDirectives(ITextTemplatingEngineHost host, TemplateProcessingSession session, List`1 directivesToBeProcessed)
This works like a charm! I made two modifications:
ReplyDelete1. Only clean the temp directory when a new new copy is made
2. if a .pdb file exists of the same name, then copy it as well
thanks for posting this!
tangible T4 Editor V1.9 now supports this new directive and provides intellisense for assemblies referenced by it! Great work guys!
ReplyDelete