I have a class, BaseEmailTemplate, that formats an email, and I want to create a derived type that can overrule the defaults. Originally my base constructor -
public BaseEmailTemplate(Topic topic)
{
CreateAddresses(topic);
CreateSubject(topic);
CreateBody(topic);
}
... (Body/Addresses)
protected virtual void CreateSubject(Topic topic)
{
Subject = string.Format("Base boring format: {0}", topic.Name);
}
And in my derived
public NewEmailTemplate(Topic topic) : Base (topic)
{
//Do other things
}
protected override void CreateSubject(Topic topic)
{
Subject = string.Format("New Topic: {0} - {1})", topic.Id, topic.Name);
}
Of course this leads to the error discussed here: Virtual member call in a constructor
So to be absolutely blunt about this - I don't want to have to call the same methods in every derived type. On the flip side, I need to be able to change any/all. I know another base has a different subset of addresses, but the body and subject will be the default.
All three methods must be called, and the ability to alter any one of them needs to be available on a per derived basis.
I mean the thing everyone seems to be saying is an unintended consequence of using virtual seems to be my exact intention.. Or maybe I'm in too deep and singly focused?
UPDATE- Clarification
I understand why virtual members in the constructor is bad, I appreciate the answers on that topic, though my question isn't "Why is this bad?" its "Ok this is bad, but I can't see what better serves my need, so what do I do?"
This is how it is currently implemented
private void SendNewTopic(TopicDTO topicDto)
{
Topic topic = Mapper.Map<TopicDTO , Topic>(topicDto);
var newEmail = new NewEmailTemplate(topic);
SendEmail(newEmail); //Preexisting Template Reader infrastructure
//Logging.....
}
I'm dealing with a child and grandchild. Where I came in there was only newemailtemplate, but I have 4 other tempaltes I now have to build, but 90% of the code is reusable. Thats why I opted to create BaseEmailTemplate(Topic topic). BaseTemplate creates things like Subject and List and other things that SendEmail is expecting to read.
NewEmailTemplate(Topic topic): BaseEmailTemplate(Topic topic): BaseTemplate, IEmailTempate
I would prefer not have to require anyone who follows my work have to know that
var newEmail = new NewEmailTemplate();
newEmail.Init(topic);
is required every single time it is used. The object would be unusable without it. I thought there were many warnings about that?