.NET类的设计问题问题、NET

2023-09-04 01:40:29 作者:蒹葭苍苍

我有一个类的问题,有一个名为Type属性。基于这种类型,我想呈现的问题一个特定的方式(可多选=单选按钮,多个答案=复选框,等...)HTML研究。我开始了与调用子方法,根据问题类型单一RenderHtml方法,但我想分离出呈现逻辑为实现接口可能会更好个人类。然而,由于这一类是坚持使用NHibernate的数据库和接口的实现依赖于房地产,我不知道如何以最佳方式布局类。

I have a class called Question that has a property called Type. Based on this type, I want to render the question to html in a specific way (multiple choice = radio buttons, multiple answer = checkboxes, etc...). I started out with a single RenderHtml method that called sub-methods depending on the question type, but I'm thinking separating out the rendering logic into individual classes that implement an interface might be better. However, as this class is persisted to the database using NHibernate and the interface implementation is dependent on a property, I'm not sure how best to layout the class.

在讨论的类:

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枚举属性,我想作出以下(只是一个例子):

Based on the QuestionType enum property, I'd like to render the following (just an example):

<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>

目前,我在一个名为RenderHtml(功能的一个大的switch语句),做肮脏的工作,但我想将其移动到更整洁。我只是不知道如何。

Currently, I have one big switch statement in a function called RenderHtml() that does the dirty work, but I'd like to move it to something cleaner. I'm just not sure how.

有什么想法?

编辑:谢谢大家的答案

我最终使用下面的接口与策略模式去:

I ended up going with the strategy pattern using the following interface:

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
}

修改后的问题类使用内部字典,像这样:

The modified Question class uses an internal dictionary like so:

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);
    }
}

看起来pretty的干净的给我。 :)

Looks pretty clean to me. :)

推荐答案

例如,您可以使用的策略模式:

让所有的HTML渲染器实现一个共同的接口,例如 IQuestionRenderer ,具有方法名渲染(问题)

的实例字典&LT; QuestionType,IQuestionRenderer&GT; 在应用程序中。填充它在初始化时,也许是基于一个配置文件。

Have an instance of Dictionary<QuestionType, IQuestionRenderer> in your application. Populate it at initialization time, perhaps based on a configuration file.

有关的问题,一个给定的情况下,这样做:渲染[question.Type] .Render(问题)

For a given instance of a question, do: renderers[question.Type].Render(question)

或者,你可以有一个名为方法 RenderXXX XXX是问题的类型,并通过使用反射调用它们。

Or, you could have methods named RenderXXX where XXX is the question type, and invoke them by using reflection.