简体   繁体   English

分配我的ICollection <T> 到ICollection属性

[英]Assigning my ICollection<T> to an ICollection property

Yes, I know that ICollection and ICollection<T> are two different things. 是的,我知道ICollectionICollection<T>是两个不同的东西。 Let me describe what I'm trying though... 让我描述一下我在想什么...

This is what I would like to do: 这是我想做的:

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;
    }
}

Question: Why is report.ReportSections.First().ReportItems null? 问题:为什么report.ReportSections.First().ReportItems空? (See comments in code above.) (请参见上面的代码中的注释。)

Here is how ContribAuthorsReport and ChapterAffiliates are defined: 这是ContribAuthorsReportChapterAffiliates的定义方式:

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; }

}

I will have other classes that inherit from ReportSectionBase, that will have different models for the ICollection. 我将拥有从ReportSectionBase继承的其他类,这些类将具有ICollection的不同模型。 I believe that this issue stems from how I have the base classes defined. 我认为这个问题源于如何定义基类。 (See below) (见下文)

My base classes. 我的基类。

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; }
} 

UPDATE: Final Result - Here is what I'm using now. 更新:最终结果 -这是我现在正在使用的东西。

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>; }
    }
}

This allows me to define a report as easy as this: 这使我可以像这样轻松定义报告:

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;
}

The problem is that your ChapterAffiliates class hides the ReportItems property inherited from ReportSectionBase. 问题是您的ChapterAffiliates类隐藏了从ReportSectionBase继承的ReportItems属性。 See the MSDN documentation on the new modifier . 请参阅有关修饰符MSDN文档 When accessing the instance through the collection, the reference is of type ReportSectionBase. 通过集合访问实例时,引用的类型为ReportSectionBase。 Therefore, the ReportItems property has NOT been set. 因此,尚未设置ReportItems属性。 The only way to access the ReportItems property of the ChapterAffiliates instance is to access it on a reference of type ChapterAffiliates. 访问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 

To solve this, I would make your ReportSectionBase a generic class. 为了解决这个问题,我将使您的ReportSectionBase成为通用类。 The type argument would specify the type of your ReportItems. type参数将指定ReportItems的类型。 This way, you do not need to make the collection virtual, as it will be provided in the base class. 这样,您无需将集合虚拟化,因为它将在基类中提供。 Also, it keeps everything type safe. 此外,它还能确保所有类型的安全。 Which is a good thing in my opinion. 我认为这是一件好事。

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"; } }
}

Also, consider not exposing settable collection properties. 另外,请考虑不要公开可设置的集合属性。 It is not recommended in MSDN collection guidelines . MSDN收集指南中不建议使用此方法。

Because you shadow the collection with new the method is not virtual, this means when you are using a ReportSectionBase variable it will not use your new collection. 因为您用new的阴影遮盖了集合,所以该方法不是虚拟的,这意味着当您使用ReportSectionBase变量时,它将不使用新的集合。

The easiest way to solve this is change your abstract class to a interface, this allows you to do a explicit implementation of the base class but also expose your generic collection. 解决此问题的最简单方法是将抽象类更改为接口,这使您可以对基类进行显式实现,但也可以公开通用集合。

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>; }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM