Creating a Class of Objects within an Object

2019-05-28 23:23发布

问题:

I have what might seem like a simple question, but for some reason I am having a problem getting my brain around the concept of having a object with multiple object with in it. For example lets say we have a object with a header and a footer with multiple objects in between.

Like a report, the header would have the name and address. The footer would have a total of the item that where bought. In between would be the line items with the part number, description and a price.

I guess the I can have a object with an header, footer and an array of line item object, all with their own properties. I am using a report as the example, because it’s the only concept that I can think of that will get close to explaining my question.

Can someone please send me a link to or explain on how to create this type of object(s).

I am using VS 2010 and VB.net and I can translate from C# to VB.

    Report Object
       Header Object
         Property Name
         Property Date
       End
       LineItem() Array Object
         Property Part Number
         Property Part Description
         Property Number of Items
         Property Per Item Price
         Property Total price
       End 
       Footer Object
         Property Total Items count
         Property Total Price
       End
     End

回答1:

Jeff, in c# and at its most basic:

public class Report
{
    // typical simple property in report
    public string ReportUid { get; set; }
    // object properties
    public Header Header { get; set; }
    public Body Body { get; set; }
    public Footer Footer { get; set; }

    public Report()
    {
        Header = new Header();
        Body = new Body();
        Footer = new Footer();
    }

    internal void CalculateFooterTotals()
    {
        // summerize the lineitems values in the footer
        Footer.TotalItems = Body.LineItems
            .Sum(x => x.Quantity);
        Footer.TotalPrice = Body.LineItems
            .Sum(x => x.Total);
    }
}

public class Header
{
    public string Name { get; set; }
    public DateTime Date { get; set; }
}

public class Body
{
    public IList<LineItem> LineItems { get; set; }

    public Body()
    {
        LineItems = new List<LineItem>();
    }
}

public class LineItem
{
    public string PartNumber { get; set; }
    public string PartDescription { get; set; }
    public int Quantity { get; set; }
    public float ItemPrice { get; set; }
    // computed 
    public float Total
    {
        get { return Quantity * ItemPrice; }
    }
}

public class Footer
{
    // populated via report.CalculateFooterTotals()
    public int TotalItems { get; internal set; }
    public float TotalPrice { get; internal set; }
}

Some of the properties are of course computed, rather than get/set.

[edit] - thought it'd be good practice to add a bit of usage, as I saw you ask Douglas this question (more than likely from DB or other source):

// usage - set up report
var report = new Report {
    ReportUid = Guid.NewGuid().ToString(),
    Header =
    {
        Name = "My new report", 
        Date = DateTime.UtcNow
    }};
// add lineitems to body (in real case, probably a loop)
report.Body.LineItems.Add(new LineItem()
    {
        Quantity = 1,
        ItemPrice = 12.30f,
        PartDescription = "New shoes", 
        PartNumber = "SHOE123"
    });
report.Body.LineItems.Add(new LineItem()
    {
        Quantity = 3, 
        ItemPrice = 2.00f, 
        PartDescription = "Old shoes", 
        PartNumber = "SHOE999"
    });
report.Body.LineItems.Add(new LineItem()
    {
        Quantity = 7, 
        ItemPrice = 0.25f, 
        PartDescription = "Classic Sox", 
        PartNumber = "SOX567"
    });
// summerize the lineitems values in the footer
report.CalculateFooterTotals();

now apply report to your canvas surface (html etc..)

private static void DispalyData(Report report)
{
    // set out the basics
    Console.WriteLine("Header");
    Console.WriteLine(report.ReportUid);
    Console.WriteLine(report.Header.Date);
    Console.WriteLine(report.Header.Name);

    // now loop round the body items
    Console.WriteLine("Items");
    foreach (var lineItem in report.Body.LineItems)
    {
        Console.WriteLine("New Item---");
        Console.WriteLine(lineItem.PartDescription);
        Console.WriteLine(lineItem.Quantity);
        Console.WriteLine(lineItem.ItemPrice);
        Console.WriteLine(lineItem.PartNumber);
        Console.WriteLine(lineItem.Total);
        Console.WriteLine("End Item---");
    }

    // display footer items
    Console.WriteLine("Footer");
    Console.WriteLine(report.Footer.TotalItems);
    Console.WriteLine(report.Footer.TotalPrice);
}

// called in code as:
DispalyData(report);

Hope this scans ok... pushed it to community wiki (via edits), as it's a universally sought after topic.

[btw] - altho you'll be aware of c# to vb.net convertors, I tried this one and it looks pretty promising: http://www.developerfusion.com/tools/convert/csharp-to-vb



回答2:

You need to create a class for each type of object. It's best to give each of them their own file.

Public Class Report
  Public Property Header As Header
  Public Property LineItems As IEnumerable(Of LineItem)
  Public Property Footer As Footer
End Class


Public Class Header
  Public Property Name As String
  ' This probably isn't the best word choice because it is a type alias in VB
  Public Property [Date] As Date
End Class


Public Class LineItem
  Public Property PartNumber As Integer
  Public Property PartDescription As String
  Public Property NumberOfItems As Integer
  Public Property PerItemPrice As Decimal
  Public Property TotalPrice As Decimal
End Class


Public Class Footer
  Public Property TotalItemsCount As Integer
  Public Property TotalPrice As Decimal
End Class

Use it like so:

Dim myReport As New Report()
Dim myHeader As New Header()
Dim lineItem1 As New LineItem()
Dim lineItem2 As New LineItem()
Dim myFooter As New Footer()
With myReport
    .Header = myHeader
    .Footer = myFooter
    .LineItems = {lineItem1, lineItem2}   
End With