是的,我知道ICollection
和ICollection<T>
是两回事。让我来描述我尝试的内容......
这就是我想做的事情:
public class SubmissionListViewModel
{
public ICollection<ProjectSubmissionViewModel> Submissions { get; set; }
public ReportBase GetContribAuthorsReport()
{
var report = new ContribAuthorsReport{ ReportType = "CSV" };
var chapAffil = new ChapterAffiliates {ReportItems = Submissions};
report.ReportSections.Add(chapAffil);
// AT this point, I would expect report.ReportSections.First().ReportItems
// to have the records from Submissions, but I have `null`.
return report;
}
}
问题: 为什么report.ReportSections.First().ReportItems
为空? (见上面代码中的评论。)
以下是ContribAuthorsReport
和ChapterAffiliates
的定义方式:
public class ContribAuthorsReport : ReportBase
{
public ContribAuthorsReport()
{
ReportSections = new List<ReportSectionBase>();
}
public override string ReportName { get { return "Contributing Affiliates' Contact Information"; } }
}
public class ChapterAffiliates : ReportSectionBase
{
public override string ReportSectionName { get { return "Chapter Affiliates"; } }
// This is what I have now
new public ICollection<ProjectSubmissionViewModel> ReportItems { get; set; }
// This won't compile
//public override ICollection<ProjectSubmissionViewModel> ReportItems { get; set; }
// This would compile, but breaks GetContribAuthorsReport()
//public override ICollection ReportItems { get; set; }
}
我将有其他继承自ReportSectionBase的类,它们将具有不同的ICollection模型。我认为这个问题源于我如何定义基类。 (见下文)
我的基础课程。
public abstract class ReportBase
{
virtual public string ReportType { get; set; }
virtual public string ReportName { get; set; }
public ICollection<ReportSectionBase> ReportSections { get; set; }
}
public abstract class ReportSectionBase
{
virtual public string ReportSectionName { get; set; }
virtual public ICollection ReportItems { get; set; }
}
更新:最终结果 - 这就是我现在正在使用的内容。
public class ReportBase
{
public ReportBase()
{
ReportSections = new List<IReportSection>();
}
public string ReportType { get; set; }
public string ReportName { get; set; }
public ICollection<IReportSection> ReportSections { get; set; }
}
public interface IReportSection
{
string ReportSectionName { get; }
ICollection ReportItems { get; set; }
}
public class ReportSection<T> : IReportSection
{
public string ReportSectionName { get; set; }
public ICollection<T> ReportItems { get; set; }
ICollection IReportSection.ReportItems
{
get { return ReportItems as ICollection; }
set { ReportItems = value as ICollection<T>; }
}
}
这使我可以像这样简单地定义报告:
public ReportBase GetContribAuthorsReport
(
ICollection<ProjectAffiliateViewModel> projectAffiliates,
ICollection<SubmissionAffiliateViewModel> submissionAffiliates
)
{
var caReport = new ReportBase { ReportType = "CSV", ReportName = "Reviewers' Contact Information" };
caReport.ReportSections.Add(new ReportSection<ProjectAffiliateViewModel> { ReportItems = projectAffiliates });
caReport.ReportSections.Add(new ReportSection<SubmissionAffiliateViewModel> { ReportItems = submissionAffiliates });
return caReport;
}
答案 0 :(得分:1)
问题是您的ChapterAffiliates类隐藏了从ReportSectionBase继承的ReportItems属性。请参阅MSDN documentation on the new modifier。通过集合访问实例时,引用的类型为ReportSectionBase。因此,尚未设置ReportItems属性。访问ChapterAffiliates实例的ReportItems属性的唯一方法是在类型为ChapterAffiliates的引用上访问它。
ChapterAffiliates a = new ChapterAffiliates { ReportItems = Submissions};
ReportSectionBase b = new ChapterAffiliates { ReportItems = Submissions};
// a.ReportItems == Submissions; returns true
// b.ReportItems == null; returns true
// ((ChapterAffiliates) b).ReportItems == Submissions; returns true
要解决这个问题,我会将ReportSectionBase作为通用类。 type参数将指定ReportItems的类型。这样,您不需要将集合设置为虚拟,因为它将在基类中提供。此外,它保证一切类型安全。在我看来,这是一件好事。
public abstract class ReportBase<TReportSection, TReportItem> where TReportSection : ReportSectionBase<TReportItem>
{
public virtual string ReportType { get; set; }
public virtual string ReportName { get; set; }
public ICollection<TReportSection> ReportSections { get; set; }
}
public abstract class ReportSectionBase<TReportItem>
{
public virtual string ReportSectionName { get; set; }
public ICollection<TReportItem> ReportItems { get; set; }
}
public class ChapterAffiliates : ReportSectionBase<ProjectSubmissionViewModel>
{
public override string ReportSectionName { get { return "Chapter Affiliates"; } }
}
public class ContribAuthorsReport : ReportBase<ChapterAffiliates, ProjectSubmissionViewModel>
{
public ContribAuthorsReport()
{
ReportSections = new List<ChapterAffiliates>();
}
public override string ReportName { get { return "Contributing Affiliates' Contact Information"; } }
}
另外,请考虑不公开可设置的集合属性。不建议在MSDN collection guidelines。
答案 1 :(得分:1)
由于您使用new
隐藏了该集合,因此该方法不是虚拟的,这意味着当您使用ReportSectionBase
变量时,它将不会使用您的新集合。
解决此问题的最简单方法是将抽象类更改为接口,这允许您显式实现基类,但也公开您的泛型集合。
public abstract class ReportBase
{
virtual public string ReportType { get; set; }
virtual public string ReportName { get; set; }
public ICollection<IReportSection> ReportSections { get; set; }
}
public interface IReportSection
{
string ReportSectionName { get; }
ICollection ReportItems { get; set; }
}
public class ContribAuthorsReport : ReportBase
{
public ContribAuthorsReport()
{
ReportSections = new List<IReportSection>();
}
public override string ReportName { get { return "Contributing Affiliates' Contact Information"; } }
}
public class ChapterAffiliates : IReportSection
{
public string ReportSectionName { get { return "Chapter Affiliates"; } }
public ICollection<ProjectSubmissionViewModel> ReportItems { get; set; }
ICollection IReportSection.ReportItems {
get { return ReportItems as ICollection; }
set { ReportItems = value as ICollection<ProjectSubmissionViewModel>; }
}
}