首页 > 解决方案 > 如何实现仅选择特定类型项目的功能?

问题描述

语境

我有一Question堂课。它有三个子类:

我有一Repository堂课,它有一个IEnumerable<Question>.


代码

问题类层次结构和容器类 Repository

class Question {}
class ChoiceQuestion : Question {}

class ShortTextQuestion : Question {}

class LongTextQuestion : Question {}

class Repository
{
    IEnumerable<Question> Questions { get; set; }
}

问题

我想Questionnaire从这些存储库中挑选几个问题。

我有IQuestionnaireBuilder一个AddSource()方法,可以帮助配置从哪个存储库中选择问题以及如何选择它们。我有QuestionnaireSource持有这种配置的类。

目前,我能够指定要从哪个存储库中选择,每个难度要选择多少个问题。我想指定它应该只选择特定子类型的问题。

例如,要选择的问题必须是ChoiceQuestionShortTextQuestion。我遇到过System.Type,但我想限制它们必须派生的类型Question


代码

问卷调查生成器

interface IQuestionnaireBuilder
{
    IQuestionnaireBuilder AddSource(Action<QuestionnaireSource> source);
}

问卷来源

class QuestionnaireSource
{
    public Repository Repository { get; set; }

    public IDictionary<QuestionDifficulty, int> { get; set; }
    
    // <Property/method to configure which subclasses to include, they must derive from Question>
}

问题难度

enum QuestionDifficulty
{ Easy, Medium, Hard }
    IQuestionnaireBuilder builder = new QuestionnaireBuilder();
    
    Repository repo1 = someExternalProvider.GetRepo(1);
    Repository repo2 = someExternalProvider.GetRepo(2);
    builder
        .AddSource(source => {
            source.Repository = repo1;
            source.Count[QuestionDifficulty.Easy] = 10;
            source.Count[QuestionDifficulty.Medium] = 7;
            source.Count[QuestionDifficulty.Hard] =  3;
            source.PickOnlySpecificSubclassesOfQuestion() // how to implement this? 
       })
       .AddSource(source => {
            source.Repository = repo2;
            source.Count[QuestionDifficulty.Easy] = 30;
            source.Count[QuestionDifficulty.Medium] = 15;
            source.Count[QuestionDifficulty.Hard] =  5;
            source.PickOnlySpecificSubclassesOfQuestion() // how to implement this? 
       })    

在上面的代码片段中,我如何实现该PickOnlySpecificSubclassesOfQuestion()部分?

标签: c#oopdesign-patternsbuilderfluent

解决方案


一种方法是使您的PickOnlySpecificSubclassesOfQuestion通用化,并传递一个代表您想要的问题类型的参数。

public void PickOnlySpecificSubclassesOfQuestion<T>()
where T : Question

在该方法中,您可以获得一个 System.Type 表示请求的问题类型,如下所示:

Type desiredTypeOfQuestion = typeof(T);

然后,给定一个IEnumerable包含所有不同类型问题的问题,您可以使用 Linq 和 Reflection 来查找可从所需类型分配的问题:

return myQuestions.Where(q => q.GetType().IsAssignableFrom(desiredTypeOfQuestion));

我相信还有其他方法也可以,但这是最容易想到的方法。


推荐阅读