Reputation: 57282
I'm trying to use T4 to create a mail message template.
I am using a preprocessed template, which, if I understoo correctly, is what I have to do if I want to generate the message at run time without introducing a dependency on the Microsoft.VisualStudio.TextTemplating
assembly.
Since I want to pass some data to my template, I added parameters to it:
<#@ template language="C#" #>
<#@ parameter name="Param1" type="System.String" #>
<#@ parameter name="Param2" type="System.
Lorem <#= Param1 #> dolor <#= Param2 #>
Then I can generate the message passing arguments like this:
static void Main(string[] args) {
var template = new LoremIpsum();
template.Session = new Dictionary<string, object>() {
{"Param1", "ipsum"},
{"Param2", "sit amet"},
};
template.Initialize();
string text = template.TransformText();
}
Since I need to generate several of these classes, I would like them all to have a common method to send a mail, something like this:
public void SendMail(string to, IDictionary<string, object> parameters)
or, even better:
public void SendMail(string to, string Param1, string Param2)
Since the generated classes are partial, it is possible to add methods to them adding another partial class declaration, but this would mean that I would have to repeat the (more or less) same code for all the generated classes.
I tried creating a base class, but if I try to do this:
<#@ template language="C#" inherits="MailTemplateBase" #>
then the generated code breaks, as the generated class was relying on the LoremIpsumBase
base class which defined some helper methods (and I really see no point in having each generated class inherit from an almost identical but distinct base class).
Upvotes: 0
Views: 1319
Reputation: 7578
I think you need to create an empty template, copy the created class and use it as your base class. You can then extend it with whatever properties you need. (you don't need to keep the empty template once you've copied the code)
For what it's worth I think what you are trying to do worked out of the box in VS 2010 RTM, but VS2010 SP1 changed the behaviour so that you can subclass templates themselves. Check out this connect issue for more info.
EDIT:
As far as putting an email method on the base goes, I probably wouldn't do it that way. You might want to think about exposing some sort of templating service that has the various methods on it that you need, e.g.:
public class TemplatingService : ITemplatingService
{
public string GenerateReminderMessage(string to, string name)
{
// Construct the template, passing in the parameters into the session as required
...
// Return the results of the template transformation
}
}
That way you're abstracted away from the actual T4 implementation so if something does break somewhere down the line you only have to fix it in one class.
And expose a mail service that uses the templating service to generate the mail contents:
public class MailService : IMailService
{
public void SendReminderEmail(string to, string name)
{
var message = this.TemplatingService.GenerateReminderMessage(to, name);
this.MailerService.SendEmail(to, message);
}
}
Note that the MailerService would just a simple wrapper around the .NET mail code, but it would allow you to unit test the MailService in isolation.
There are probably more ways you could abstract it out, but that would be a start.
Hope that helps.
Upvotes: 2
Reputation: 48314
It sounds like you assumption is that the constructor injection is the only way to inject the data to a class. I guess however that metod/property injections are better options in this scenario.
I don't have the compiler at hand and can't verify it for sure but it seems it may work.
Upvotes: 0