У меня есть класс под названием "Вопрос", который имеет свойство "Тип". Основываясь на этом типе, я хочу передать вопрос html определенным образом (множественный выбор = радиокнопки, несколько ответов = флажки и т.д.). Я начал с одного метода RenderHtml, который называл под-методы в зависимости от типа вопроса, но я думаю, что отделить логику визуализации от отдельных классов, которые реализуют интерфейс, может быть лучше. Однако, поскольку этот класс сохраняется в базе данных с использованием NHibernate, и реализация интерфейса зависит от свойства, я не уверен, как лучше всего компоновать класс.
Этот класс:
public class Question
{
public Guid ID { get; set; }
public int Number { get; set; }
public QuestionType Type { get; set; }
public string Content { get; set; }
public Section Section { get; set; }
public IList<Answer> Answers { get; set; }
}
Основываясь на свойстве перечисления QuestionType, я бы хотел отобразить следующее (просто пример):
<div>[Content]</div>
<div>
<input type="[Depends on QuestionType property]" /> [Answer Value]
<input type="[Depends on QuestionType property]" /> [Answer Value]
<input type="[Depends on QuestionType property]" /> [Answer Value]
...
</div>
В настоящее время у меня есть один большой оператор switch в функции RenderHtml(), которая выполняет грязную работу, но я хотел бы переместить ее на что-то более чистое. Я просто не знаю, как это сделать.
Любые мысли?
EDIT: Спасибо всем за ответы!
В итоге я перешел к шаблону стратегии, используя следующий интерфейс:
public interface IQuestionRenderer
{
string RenderHtml(Question question);
}
И следующая реализация:
public class MultipleChoiceQuestionRenderer : IQuestionRenderer
{
#region IQuestionRenderer Members
public string RenderHtml(Question question)
{
var wrapper = new HtmlGenericControl("div");
wrapper.ID = question.ID.ToString();
wrapper.Attributes.Add("class", "question-wrapper");
var content = new HtmlGenericControl("div");
content.Attributes.Add("class", "question-content");
content.InnerHtml = question.Content;
wrapper.Controls.Add(content);
var answers = new HtmlGenericControl("div");
answers.Attributes.Add("class", "question-answers");
wrapper.Controls.Add(answers);
foreach (var answer in question.Answers)
{
var answerLabel = new HtmlGenericControl("label");
answerLabel.Attributes.Add("for", answer.ID.ToString());
answers.Controls.Add(answerLabel);
var answerTag = new HtmlInputRadioButton();
answerTag.ID = answer.ID.ToString();
answerTag.Name = question.ID.ToString();
answer.Value = answer.ID.ToString();
answerLabel.Controls.Add(answerTag);
var answerValue = new HtmlGenericControl();
answerValue.InnerHtml = answer.Value + "<br/>";
answerLabel.Controls.Add(answerValue);
}
var stringWriter = new StringWriter();
var htmlWriter = new HtmlTextWriter(stringWriter);
wrapper.RenderControl(htmlWriter);
return stringWriter.ToString();
}
#endregion
}
Измененный класс Question использует внутренний словарь, например:
public class Question
{
private Dictionary<QuestionType, IQuestionRenderer> _renderers = new Dictionary<QuestionType, IQuestionRenderer>
{
{ QuestionType.MultipleChoice, new MultipleChoiceQuestionRenderer() }
};
public Guid ID { get; set; }
public int Number { get; set; }
public QuestionType Type { get; set; }
public string Content { get; set; }
public Section Section { get; set; }
public IList<Answer> Answers { get; set; }
public string RenderHtml()
{
var renderer = _renderers[Type];
return renderer.RenderHtml(this);
}
}
Выглядит довольно чисто для меня.:)