0

我似乎无法从基类调用派生类中重写属性的设置器。这似乎是一个人应该能够做的事情,但我显然错过了一些东西。在下面 SearchSurveyBase 类的 DisplayQuestion 方法中,这一行似乎没有做任何设置:

VisibleQuestions.Add(sqc.SurveyQuestion.ID);

VisibleQuestions 是在派生类中被覆盖的抽象列表。吸气剂似乎从基础上工作得很好。我可以看到它们在调试时被派生类击中。但是,setter 似乎根本没有工作。getter 被称为很好,但 setter 永远不会设置。我在这里想念什么?有一个更好的方法吗?

基类:

public abstract class SearchSurveyBase : System.Web.UI.UserControl
{
    public abstract List<int> VisibleQuestions { get; set; }

    public abstract void SetupControls();

    protected void AddQuestion(Accordion accSection, Question question)
    {
        SearchQuestionControl searchQuestionControl = GetQuestionControl(question.ControlType);

        if (searchQuestionControl != null)
        {
            //QuestionVisible is a method that checks to see if the object's id is in the VisibleQuestions list
            searchQuestionControl.Visible = QuestionVisible(question);

            if (!searchQuestionControl.Visible)
            {
                string btnID = "lb_" + accSection.ID.ToString() + "_" + accSection.Panes.Count;
                LinkButton btn = new LinkButton();
                btn.ID = btnID;
                btn.Text = question.Text;
                btn.CommandArgument = questionPane.ID;
                btn.Command += new CommandEventHandler(DisplayQuestion);
                questionPane.HeaderContainer.Controls.Add(btn);
            }

            questionPane.ContentContainer.Controls.Add(searchQuestionControl);
            searchQuestionControlList.Add(searchQuestionControl);
        }
        accSection.Panes.Add(questionPane);
    }

    private void DisplayQuestion(object sender, CommandEventArgs e)
    {
        SearchQuestionControl sqc = null;
        AccordionPane pane = (AccordionPane)UIUtilities.FindControlRecursive(RootControl, e.CommandArgument.ToString());
        if (pane != null && pane.ContentContainer.HasControls() && pane.ContentContainer.Controls[0] is SearchQuestionControl)
        {
            sqc = (SearchQuestionControl)pane.ContentContainer.Controls[0];
        }

        if (sqc != null)
        {
            if (!sqc.Visible)
            {
                //Removed a bunch of lines that aren't relevant to the question per request.
                VisibleQuestions.Add(sqc.SurveyQuestion.ID);
            }
        }
    }
}

派生类:

public partial class SearchSurveyAccordion : SearchSurveyBase
{
    override public List<int> VisibleQuestions
    {
        get
        {
            // hfVisibleQuestions is a HiddenField control on the .ascx page that inherits this class.
            if (!string.IsNullOrWhiteSpace(hfVisibleQuestions.Value))
            {
                string[] vals = hfVisibleQuestions.Value.Split(',');
                List<int> vqs = new List<int>(Array.ConvertAll<string, int>(vals, (x => Convert.ToInt32(x))));
                return vqs;
            }
            else
            {
                return new List<int>();
            }
        }
        set
        {
            hfVisibleQuestions.Value = string.Join(",", value.Select(n => n.ToString()).ToArray());
        }
    }

    // This method is called during the Page_Init of the page that is consuming this user control.
    override public void SetupControls()
    {
        if (base.survey != null && base.survey.QuestionList != null && base.survey.QuestionList.Count > 0)
        {
            BuildAccordion(base.survey.QuestionList);
        }
    }

    private void BuildAccordion(List<Question> questionList)
    {
        Accordion accSection = null;
        foreach (Question question in questionList)
        {
            accSection = base.AddSection(accSurvey, defaultSectionHeader);
            AddQuestion(accSection, question);
        }
    }
}

TL;博士?这是问题的简短版本。

我有一个基类和一个派生类。我希望基类中的方法能够设置在派生类中被覆盖的抽象属性的值,但它对我不起作用。

4

3 回答 3

1

如果您期望以下语句调用 VisibleQuestions 的设置器,那么您就错了:

VisibleQuestions.Add(sqc.SurveyQuestion.ID);

此语句调用List<int>VisibleQuestions getter 返回的实例的 Add 方法。

如果您为 VisibleQuestions 分配了一个值,则会使用 setter,如下所示:

VisibleQuestions = new List<int>();
于 2012-06-13T18:06:29.690 回答
1

您没有在该行调用 setter。您正在调用返回一个列表的 getter,您可以在其中添加一个元素。但是,下次您访问同一个 getter 时,您会创建一个新列表(没有添加的元素),您会重新返回该列表

于 2012-06-13T18:06:43.187 回答
0

来自MSDN - 使用属性(C# 编程指南) - 设置访问器

当您为 property 赋值时,将使用提供新值的参数调用 set 访问器。

仅当您实际设置属性值时才会调用 setter。在您的情况下,您正在调用您的 getter,它根据基础字段的值返回一个新列表。如果您想在更新列表后更新该基础字段,则需要将属性的值设置为更新后的列表,如下所示:

// Calls the getter and returns a new list
List<string> questions = VisibleQuestions; 

// Updates the list, but does not trigger the setter
questions.Add(sqc.SurveyQuestion.ID); 

// Calls the setter
VisibleQuestions = questions;
于 2012-06-13T18:10:18.787 回答