我试图通过创建一个小测验应用程序来自我学习c#(asp.net核心),但是我对如何创建复杂的数据模型感到困惑。想象一个带有如下问题集合的测验模型:
public class Quiz
{
public int Id { get; set; }
public Icollection<Question> Questions { get; set; }
}
但是如果我想要不同种类的问题(多项选择,对/错,文本答案...),我可以使用继承来缩短某些内容吗?还是我只需要为每种类型的问题创建一个不同的模型并将其放入在这样的:
Public class Quiz
{
public Icollection<MultipleChoicQuestion> Questions { get; set; }
public Icollection<TrueOrFalseQuestion> Questions { get; set; }
public Icollection<TextQuestion> Questions { get; set; }
}
一种方法是创建一个IQuestion
接口,其中包含运行测验所需的所有面向公众的方法和属性:
public interface IQuestion
{
void AskQuestion();
string CorrectAnswer { get; }
bool IsCorrect { get; }
}
然后您可以在Quiz
类中收集此接口:
public class Quiz
{
public ICollection<IQuestion> Questions { get; set; }
}
现在我们可以创建单独的类,每个类以各自的方式实现IQuestion
属性和方法。
例如:
public class TextQuestion : IQuestion
{
public bool IsCorrect => string.Equals(_userAnswer.Trim(), _answer.Trim(),
StringComparison.OrdinalIgnoreCase);
public string CorrectAnswer { get; }
private readonly string _question;
private readonly string _answer;
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;
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.WriteLine(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;
public bool _correctAnswer;
private bool _userAnswer;
public TrueOrFalseQuestion(string question, bool correctAnswer)
{
_question = question;
_correctAnswer = correctAnswer;
}
public void AskQuestion()
{
_userAnswer = GetBoolFromUser(_question);
}
private static bool GetBoolFromUser(string prompt)
{
bool result;
do
{
Console.Write(prompt + ": ");
} while (!bool.TryParse(Console.ReadLine(), out result));
return result;
}
}
示例用法
class Program
{
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!"
: $"The correct answer is: {question.CorrectAnswer}");
}
Console.WriteLine("Your final score is: " +
$"{quiz.Questions.Count(q => q.IsCorrect)}/{quiz.Questions.Count}");
GetKeyFromUser("\nPress any key to exit...");
}
}