Using inheritance and parameters at the same time in t4 - visual-studio

I am using t4 (text templates) to generate emails and would like a common base class for my templates. To do this, I create an email base template and have all my email templates inherit from it. Like so:
The base template:
<## template language="C#" #>
The derived template:
<## template language="C#" inherits="BaseTemplate" #>
<## parameter name="Param" type="System.String" #>
Template! Param=<#= Param #>
Note the parameter in the derived template. When this is present, it causes the template to have an Initialize method. And, because the the derived template derives from a base template, the declaration of the Initialize method in the derived template uses the keyword "override". However, there is no Initialize method on the base template. This causes an error:
'Template.Initialize()': no suitable method found to override
I can work around this by declaring a dummy parameter in the base template:
<## template language="C#" #>
<## parameter name="DummyParam" type="System.String" #>
Which causes an Initialize method to be generated in the base template, from which the derived template may override.
My questions is, am I missing something? Having to add a dummy parameter to pacify the compiler make it seem like I'm doing something wrong.

Related

How to define data model for include template in freemarker

I am trying to process the freemarker template through template.process(,) and loading the template from database(mongo) through the TemplateLoader interface.Here I want to define the different data-model for the included template. Mainly I want to define template.process for an individual included template.
Also, is there any way through which we can execute the business logic while processing the template.
Will it be a good idea to process the template while implementing the templateloader interface?
If by including a template you mean using <#include ...>, that's basically for composing a single template from reusable fragments, so it can't have a different data-model than the including template. But you could use your own custom directive implementation (see TemplateDirectiveModel) to do a whole new template processing inside another, just pass Environment.getOut() to Template.process so that it writes to the output of the parent template processing.

What does Include mean in API Blueprint files?

I can't see any mention of it in the API Blueprint spec, although there was a feature request to add an include directive for including other files.
Include is not to be confused with the non-standard directive of the same name for including other files (although the aglio tool for API Blueprint does support the latter).
Include is defined in the MSON specification, which is referred to by the API Blueprint spec. For example, in the Data Structures section of an API Blueprint file, the named types defined therein are defined using MSON.
Include is like extends in Java - it makes the type that is currently being defined inherit all the fields of the specified "supertype". The keyword Include may be followed by the name of a named type (its usual usage) or, somewhat strangely, by an inline type definition:
MSON defines a Mixin Type that supports multiple inheritance from
another Named Type. The Named Type being inherited MUST be a Structure
Type or its sub-type.
Nested Member Types defined in and inherited from the mixed-in Named
Type are added at the same indentation level of the Mixin Type.
Mixin Type → - Include Type Name | - Include Type Definition

How do you change the output of a T4 template from a base class?

I want to create a tool as a base class to a T4 template for generating code at design time within Visual Studio .NET. I want my TextTransformation derived base class to have the final say as to what gets output into the generated file. The problem is that using .NET reflector I cannot find a method that I can override (or declare as new) or any event to hook into to change the contents of the GenerationEnvironment property before it gets used by the T4 framework.
Here is an example of the base class:
public class MyTool
: TextTransformation
{
public override void Initialize()
{
// Initialize My Tool
base.Initialize();
}
// Override the text that is generated from the T4 template and modify it
// (strip out some well known .NET attributes) here.
}
And it would be inherited from a T4 template like this:
<## template debug="false" hostspecific="true" language="C#" inherits="MyTool" #>
<## assembly name="System.Core" #>
<## assembly name="MyTool.dll" #>
<## assembly name="Microsoft.VisualStudio.TextTemplating.10.0" #>
<## import namespace="System.Linq" #>
<## import namespace="System.Text" #>
<## import namespace="System.Collections.Generic" #>
<## import namespace="MyTool" #>
<## output extension=".cs" #>
[Ender]
public interface INinjaEnder
{
INinja Build();
}
[Required]
public interface INinjaNamed<TRemainder>
{
TRemainder Named(string name);
}
public interface INinjaCostume<TRemainder>
{
TRemainder WithCostume(Costume costume);
}
I can hit breakpoints in the Initialize() method or the Dispose() method (when overridden) in MyTool, but there doesn't seem to be anything in between I can use for modifying the output. Some options I am considering:
Using the Dispose() method to create a separate file to output with the changed contents and just ignoring the output of the T4 template altogether. Unfortunately, generating a file with the same name in the Dispose() method doesn't work because it gets overwritten by the original text.
Forcing the end user to add a method call at the end of every template so I can run what I need to at the right time.
Override the WriteLine() and/or Write() methods (using new) and use them to strip out the text I don't want in the final file. This will likely entail RegEx matches on the output of the GenerationEnvironment so I can see if the code is in there and is completely generated before stripping it out.
I also thought of subclassing StringBuilder to override the ToString() method (the GenerationEnvironment returns a StringBuilder), but the StringBuilder class is sealed.
I should mention that I am targeting all editions (including express editions) of Visual Studio 2010, 2012, and 2013. I noticed that there were some pretty big differences in T4 between 2010 and 2012, so I need to come up with a solution that works in both environments.
Some Context
My reasons for going down this path are:
T4 is supported by express editions, custom tools (IVsSingleFileGenerator) and designers are not. A large part of my target audience (open source developers) will likely be using an express edition.
I want the user to specify the input as code (interfaces and attributes through the T4 template) so they don't have a steep learning curve to use my tool by having to input something more abstract such as XML, diagrams, or a designer.
I don't want the user to have to set a reference to my DLL (and thus have to ship the DLL with their code) in order to use my tool. Using T4 I can strip the attributes out of the final code after the generator is done using them, so only my tool needs to have a reference to the attributes.
T4 supports dependency injection through property injection of the base class, so my users will be able to supply their own extensions to my tool.
I can support both VB and C# T4 templates without creating too much duplicate code (since most of it will be in my DLL).
However, I will accept architectural advice if there is a better choice available than a T4 base class.

Magento objects in *.phtml files

1) What $this/$resource variables refer to in Magento .phtml files?
2) Where do I find the list of methods I can use with $this/$resource?
print_r displays huge objects which functionality is not very easy to understand.
The template files (.phtml) are included in the block methods so a proper html can be returned. See the method Mage_Core_Block_Template::fetchView.
All of the block classes that have a template associated extend the Mage_Core_Block_Template class.
So $this is actually the current block class that is being used.
In theory one template can be used by multiple block classes. But this rarely happens.
If you don't know what $this is just add this in the template file:
echo get_class($this);
and you will get the class name.
If you want the available methods you can do this:
echo "<pre>"; print_r(get_class_methods($this));echo "</pre>";
But ...you will see that you are able to call some methods that don't really exist.
Because the class Mage_Core_Block_Template extends Varien_Object that implements the method __call you will be able to call any method that starts with get, set, uns, has without getting an error even if the method does not exist.
I haven't seen a phtml with the variable $resource but you can treat that the same as $this.
I didn't understand $resource that you are referencing with. But however $this stands for block that defines that template.
To make it more clear, suppose you have a layout code that seems like this
<some_handle>
<reference name="content">
<block type="xxx/yyy" name="custom.block" as="custom.block" template="custom/template.phtml" />
</reference>
</some_handle>
Now above in our demo layout, you can see a block is defined, which defines a template template.phtml. Now your template.phtml may look like this.
location : app/design/frontend/<package>/<theme>/template/custom/template.phtml
<div>
<?php $value = $this->getSomeMethod(); ?>
</div>
Here $this stands for the block that holds this template. In this case, $this is an instance of Namespace_Modulename_Block_Yyy block. (assume xxx stand for Namespace_Modulename module.).
So the method getSomeMethod() is not defined in this class, it will definitely shows an error.
Hope that gives you an idea.

An academic query about T4 templates

Ok,
I'm thinking a little ahead here in my current project, so I apologize for how vague this question is going to be. Is it possible in one project of a solution to have a T4 template that references one of the other assemblies in the solution and inspects the exported types of the other assembly and uses their metadata to build up other code? I don't need to reference the types in that assembly directory, I just need to be able to get a list of all of them that derive from a particular base class and some metadata about them. I'm thinking of doing this specifically for some objects that are built up from a common base class and dumped to the database by NHibernate as an easy way to generate DTO classes from them for throwing at the client during AJAX calls. I'm not looking for an absolutely perfect solution, just one that gets a lot of the easy cases out of the way.
Again, I don't really have a specific example. I'm a few days out from running into this problem head-on, but it occurred to me that this option might cover a lot of the cases I might run into.
Thoughts?
Yep, this should be fine - you can use the <## assembly #> directive and also use $(SolutionDir) and other VS macros to get a starting point to navigate to your other project's output. Then you can use reflection to read the metadata you're interested in.
I was trying to achieve something similar and it works fine. In the example .tt file below, the name of my own assembly in the same solution that I am referring to is SomeLibrary. The class I am reflecting on is an interface called SomeLibrary.SomeInterface. There are ways to make this more generic, but I did not want to make the sample too complicated. Also, please do not pay attention to the overall result of this template, this is just to give you an impression on how it would work:
<## template language="C#" #>
<## output extension=".cs" #>
<## assembly name="$(SolutionDir)$(SolutionName)\bin\$(ConfigurationName)\$(SolutionName).dll" #>
<## import namespace="System.Reflection" #>
<#
Type someIType = typeof(SomeLibrary.SomeInterface);
#>
namespace SomeLibrary
{
class <#=someIType.Name#>Impl: <#=someIType.Name#>
{
<#=someIType.Name#> encapsulatedIntf;
public <#=someIType.Name#>Impl(<#=someIType.Name#> anIntf)
{
encapsulatedIntf = anIntf;
}
// Methods to be implemented:
<#
MethodInfo[] methods = someIType.GetMethods();
foreach (MethodInfo m in methods)
{
#>
// <#=m#>;
<#
}
#>
}
}
In my case, this results in
namespace SomeLibrary
{
class SomeInterfaceImpl: SomeInterface
{
SomeInterface encapsulatedIntf;
public SomeInterfaceImpl(SomeInterface anIntf)
{
encapsulatedIntf = anIntf;
}
// Methods to be implemented:
// Int32 someMethod(Int32);
// System.String someOtherMethod();
}
}

Resources