创建复杂的数据结构

Creating a complex data structure

我正在尝试通过创建一个小测验应用程序自学 c#(asp.net 核心),但我对如何创建复杂的数据模型感到困惑。 想象一个包含如下问题集合的测验模型:

    public class Quiz
    {
       public int Id { get; set; }
       public Icollection<Question> Questions { get; set; }
    }

但是如果我想要不同类型的问题(多项选择,true/false,文本答案...)我可以使用继承来缩短一些东西还是我只需要为每种类型创建一个不同的模型的问题,并把它们像这样:

Public class Quiz
{
   public Icollection<MultipleChoicQuestion> Questions { get; set; }
   public Icollection<TrueOrFalseQuestion> Questions { get; set; }
   public Icollection<TextQuestion> Questions { get; set; }
}

一种方法是创建一个 IQuestion 接口,其中包含 运行 测验所需的所有 public-facing 方法和属性:

public interface IQuestion
{
    void AskQuestion();
    string CorrectAnswer { get; }
    bool IsCorrect { get; }
}

那你就可以在你的Quizclass中有一个collection这个界面了:

public class Quiz
{
    public ICollection<IQuestion> Questions { get; set; }
}

现在我们可以创建单独的 class 实体,每个实体都以自己的方式实现 IQuestion 属性和方法。

例如:

public class TextQuestion : IQuestion
{
    public bool IsCorrect => string.Equals(_userAnswer?.Trim(), CorrectAnswer?.Trim(),
        StringComparison.OrdinalIgnoreCase);

    public string CorrectAnswer { get; }

    private readonly string _question;
    private string _userAnswer;

    public TextQuestion(string question, string answer)
    {
        _question = question;
        CorrectAnswer = answer;
    }

    public void AskQuestion()
    {
        Console.WriteLine(_question);
        _userAnswer = Console.ReadLine();
    }
}

public class MultipleChoiceQuestion : IQuestion
{
    public bool IsCorrect => _userIndex == _correctIndex + 1;

    public string CorrectAnswer => (_correctIndex + 1).ToString();

    private readonly string _question;
    private readonly List<string> _choices;
    private readonly int _correctIndex;
    private int _userIndex;

    public MultipleChoiceQuestion(string question, List<string> choices, int correctIndex)
    {
        _question = question;
        _choices = choices;
        _correctIndex = correctIndex;
    }

    public void AskQuestion()
    {
        Console.WriteLine(_question);

        for (var i = 0; i < _choices.Count; i++)
        {
            Console.WriteLine($"{i + 1}: {_choices[i]}");
        }

        _userIndex = GetIntFromUser($"Answer (1 - {_choices.Count}): ",
            i => i > 0 && i <= _choices.Count);
    }

    private static int GetIntFromUser(string prompt, Func<int, bool> validator = null)
    {
        int result;

        do
        {
            Console.Write(prompt);
        } while (!int.TryParse(Console.ReadLine(), out result) &&
                 (validator == null || validator.Invoke(result)));

        return result;
    }
}

public class TrueOrFalseQuestion : IQuestion
{
    public bool IsCorrect => _userAnswer == _correctAnswer;

    public string CorrectAnswer => _correctAnswer.ToString();

    private readonly string _question;
    private readonly bool _correctAnswer;
    private bool _userAnswer;

    public TrueOrFalseQuestion(string question, bool correctAnswer)
    {
        _question = question;
        _correctAnswer = correctAnswer;
    }

    public void AskQuestion()
    {
        _userAnswer = GetBoolFromUser(_question + " (true/false)");
    }

    private static bool GetBoolFromUser(string prompt)
    {
        bool result;

        do
        {
            Console.Write(prompt + ": ");
        } while (!bool.TryParse(Console.ReadLine(), out result));

        return result;
    }
}

示例用法

static void Main()
{
    var quiz = new Quiz
    {
        Questions = new List<IQuestion>
        {
            new MultipleChoiceQuestion("Which color is also a fruit?",
                new List<string> {"Orange", "Yellow", "Green"}, 0),
            new TextQuestion("What is the last name of our first president?", 
                "Washington"),
            new TrueOrFalseQuestion("The day after yesterday is tomorrow", false),
        }
    };

    foreach (var question in quiz.Questions)
    {
        question.AskQuestion();
        Console.WriteLine(question.IsCorrect
            ? "Correct!\n"
            : $"The correct answer is: {question.CorrectAnswer}\n");
    }

    Console.WriteLine("Your final score is: " +
        $"{quiz.Questions.Count(q => q.IsCorrect)}/{quiz.Questions.Count}");

    GetKeyFromUser("\nPress any key to exit...");
}

正如您标记的那样,这个问题与 .NET Core 或 EF 并不完全相关,它是关于数据建模的。

对于那些有点不同类型的模型,我建议你做如下。

这是 Quiz 模型。

public class Quiz
{
    public int Id { get; set; }
    public List<Question> Questions { get; set; }
}

关于枚举的问题

public class Question
{
    public int Id { get; set; }

    public QuestionType Type { get; set; }

    public List<Answer> Answers { get; set; }
}

public enum QuestionType
{
    MultipleChoice,
    TrueFalse,
    Text
}

最后一个Answers

public class Answer
{
    public int Id { get; set; }

    public int QuestionId { get; set; } 

    public Question Question { get; set; }

    public bool IsCorrect { get; set; }

    public string Value { get; set; }
}

对于这种方式,应用层将处理所有过程,但您将非常容易地存储数据。

对于 MultipleChoice 个问题,您添加多个答案并设置 IsCorrect = true 个正确的答案。

对于 TrueFalse,仅添加 2 个答案并设置 IsCorrect = true 为正确答案。

对于 Text,仅添加 1 个答案并设置 IsCorrect = true