Author Topic: Nested Collections of Classes  (Read 3994 times)

0 Members and 1 Guest are viewing this topic.

DBARANAS

  • Guest
Nested Collections of Classes
« on: September 18, 2006, 07:54:44 AM »
This is not 100% ACAD specific but I think it relates to good program design

First off I ran across this:

http://www.iai-international.org/Model/R2x3_final/index.htm

It is basically an object model/spec of building information model (BIM). I think it is a good reference and shows OOP concepts related to application design. Also there is an SDK for it.

I am trying to get my app to follow along with parts it and I have a test example that reads an XML file and constructs nested classes. All phyical object types are each serialized into flat binary files and the XML file is what loads them and nests them together.

I works OK except when it writes an XML file it flattens the file. It has something to do with how the rows are added to the datable.

here is a file that will load OK. The classes will nest together from this
Code: [Select]
<?xml version="1.0" standalone="yes"?>
<Project>
  <Buildings>
    <Building>
      <RefNo>1</RefNo>
      <Name>Building 1</Name>
    </Building>
  </Buildings>
  <Storeys>
    <Storey>
      <RefNo>1</RefNo>
      <BuildingRefNo>1</BuildingRefNo>
      <Name>Storey 1</Name>
    </Storey>
    <Storey>
      <RefNo>2</RefNo>
      <BuildingRefNo>1</BuildingRefNo>
      <Name>Storey 2</Name>
    </Storey>
  </Storeys>
  <Walls>
    <Wall>
      <RefNo>1</RefNo>
      <StoreyRefNo>1</StoreyRefNo>
      <Name>Wall 1</Name>
    </Wall>
    <Wall>
      <RefNo>2</RefNo>
      <StoreyRefNo>1</StoreyRefNo>
      <Name>Wall 2</Name>
    </Wall>
  </Walls>
</Project>

This is how it writes the XML file when I add a building. The new building is not nested as it should be
Code: [Select]
<?xml version="1.0" standalone="yes"?>
<Project>
  <Buildings>
    <Building>
      <RefNo>1</RefNo>
      <Name>Building 1</Name>
    </Building>
  </Buildings>
   
 <Building>!!!!!
    <RefNo>0</RefNo>
    <Name>Building 0</Name>
  </Building>

  <Storeys>
    <Storey>
      <RefNo>1</RefNo>
      <BuildingRefNo>1</BuildingRefNo>
      <Name>Storey 1</Name>
    </Storey>
    <Storey>
      <RefNo>2</RefNo>
      <BuildingRefNo>1</BuildingRefNo>
      <Name>Storey 2</Name>
    </Storey>
  </Storeys>
  <Walls>
    <Wall>
      <RefNo>1</RefNo>
      <StoreyRefNo>1</StoreyRefNo>
      <Name>Wall 1</Name>
    </Wall>
    <Wall>
      <RefNo>2</RefNo>
      <StoreyRefNo>1</StoreyRefNo>
      <Name>Wall 2</Name>
    </Wall>
  </Walls>
</Project>


I think the problem is in the sub just below. I have been trying for a few days to get those few lines to put the row inside <Buildings></Buildings> with out any luck. There doesn't seem to be an easy way to do this, it just doesn't make sense..... :ugly:

Code: [Select]
Imports System
Imports System.Data
Imports system.Xml.Serialization

Public Class DataTables

    Public Sub AddBuilding(ByVal ref As Integer)

        Dim BuildingTable As DataTable = oProjectDS.Tables("Building")
        Dim oRow As DataRow = BuildingTable.NewRow

        oRow("RefNo") = ref.............................!
        oRow("Name") = "Building " & ref.......................!
        BuildingTable.Rows.Add(oRow)....................!

    End Sub
    Public Sub Delete(ByVal obj As Integer, ByVal ref As Integer)

        Dim dt As DataTable = New DataTable()
        Dim ObjType As New DataColumn(F.ObjectString(obj))
        Dim ObjRef As New DataColumn(ref)

        dt.Columns.Remove(ObjType)
        dt.Columns.Add(ObjRef)
        oProjectDS.Tables.Add(dt)

    End Sub
End Class
Public Class Project
    Inherits System.Collections.CollectionBase
    Private m_oBuildings As Buildings

    Public ReadOnly Property Buildings() As Buildings
        Get
            Dim oBuilding As Building
            m_oBuildings = New Buildings
            For Each oBuilding In Me
                m_oBuildings.Add(oBuilding)
            Next
            Return m_oBuildings
        End Get
    End Property

    Private Function Add(ByVal oBuilding As Building) As Boolean
        Try
            List.Add(oBuilding)
            Return True
        Catch E As System.Exception
            Return False
        End Try
    End Function

    Public Function Load(ByVal oProject As DataSet) As Boolean

        Try

            Dim oBuildingRow As DataRow

            For Each oBuildingRow In oProject.Tables("Building").Rows
                Dim oBuilding As New Building

                With oBuilding
                    .RefNo = oBuildingRow.Item("RefNo")
                    .Name = oBuildingRow.Item("Name")
                    .Storeys = New Storeys

                    Dim oStoreyRow As DataRow
                    For Each oStoreyRow In oBuildingRow.GetChildRows(oProject.Relations("StoreyToBuilding"))
                        Dim oStorey As New Storey
                        With oStorey
                            .RefNo = oStoreyRow.Item("RefNo")
                            .Name = oStoreyRow.Item("Name")
                            .Walls = New Walls

                            Dim oWallRow As DataRow
                            For Each oWallRow In oStoreyRow.GetChildRows(oProject.Relations("WallToStorey"))
                                Dim oWall As New WallPanel
                                With oWall
                                    .RefNo = oWallRow.Item("RefNo")
                                    .Name = oWallRow.Item("Name")
                                End With
                                .Walls.Add(oWall)
                                oWall = Nothing
                            Next
                        End With
                        .Storeys.Add(oStorey)
                        oStorey = Nothing
                    Next
                End With
                Me.Add(oBuilding)
                oBuilding = Nothing
            Next
            Return True
        Catch ex As System.Exception
            Return False
        End Try
    End Function

End Class
Public Class Buildings
    Inherits System.Collections.CollectionBase

    Public Function Add(ByVal oBuilding As Building) As Boolean
        Try
            List.Add(oBuilding)
            Return True
        Catch E As System.Exception
            Return False
        End Try
    End Function

End Class
Public Class Building

    Private m_oStoreys As Storeys
    Private m_iRefNo As Integer
    Private m_sName As String

    Public Property RefNo() As Integer
        Get
            Return m_iRefNo
        End Get
        Set(ByVal value As Integer)
            m_iRefNo = value
        End Set
    End Property
    Public Property Name() As String
        Get
            Return m_sName
        End Get
        Set(ByVal Value As String)
            m_sName = Value
        End Set
    End Property
    Public Property Storeys() As Storeys
        Get
            Return m_oStoreys
        End Get
        Set(ByVal Value As Storeys)
            m_oStoreys = Value
        End Set
    End Property

End Class
Public Class Storeys
    Inherits System.Collections.CollectionBase

    Public Function Add(ByVal oStorey As Storey) As Boolean
        Try
            List.Add(oStorey)
            Return True
        Catch E As System.Exception
            Return False
        End Try
    End Function
End Class
Public Class Storey

    Private m_iRefNo As Integer
    Private m_sName As String
    Private m_oWalls As Walls
    Public Property RefNo() As Integer
        Get
            Return m_iRefNo
        End Get
        Set(ByVal Value As Integer)
            m_iRefNo = Value
        End Set
    End Property
    Public Property Name() As String
        Get
            Return m_sName
        End Get
        Set(ByVal Value As String)
            m_sName = Value
        End Set
    End Property
    Public Property Walls() As Walls
        Get
            Return m_oWalls
        End Get
        Set(ByVal Value As Walls)
            m_oWalls = Value
        End Set
    End Property

End Class
Public Class Walls
    Inherits System.Collections.CollectionBase

    Public Function Add(ByVal oWallPanel As WallPanel) As Boolean
        Try
            List.Add(oWallPanel)
            Return True
        Catch E As System.Exception
            Return False
        End Try
    End Function
End Class

Code: [Select]
    Private Sub cmdLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdLoad.Click

        Dim sPath As String = "f:\frmwhr\"
        oProjectDS.ReadXml(sPath & "Database.xml")

        'Me.WriteBinary(sPath & "Database.bin", oProjectDS)
        'oProjectDS = Me.ReadBinary(sPath & "Database.bin")

        If Not oProjectDS Is Nothing Then
            With oProjectDS.Relations
                .Add("StoreyToBuilding", oProjectDS.Tables("Building").Columns("RefNo"), oProjectDS.Tables("Storey").Columns("BuildingRefNo"))
                .Add("WallToStorey", oProjectDS.Tables("Storey").Columns("RefNo"), oProjectDS.Tables("Wall").Columns("StoreyRefNo"))
            End With
            With oProject
                If .Load(oProjectDS) Then
                    Dim oBuilding As Building
                    For Each oBuilding In oProject.Buildings
                        MessageBox.Show("Building = " & oBuilding.Name)
                        Dim oStorey As Storey
                        For Each oStorey In oBuilding.Storeys
                            MessageBox.Show("Storey = " & oStorey.Name)
                            Dim oWall As WallPanel
                            For Each oWall In oStorey.Walls
                                MessageBox.Show("Wall = " & oWall.Name)
                            Next
                        Next
                    Next
                Else
                    MessageBox.Show("Error Loading XML File")
                End If
            End With
        End If

    End Sub

    Private Sub cmdAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdAdd.Click

        Dim sPath As String = "f:\frmwhr\"
        Dim a As New Building
        Dim b As New DataTables

        oProject.Buildings.Add(a)
        b.AddBuilding(a.RefNo)
        oProjectDS.WriteXml(sPath & "Database.xml")

    End Sub
End Class
« Last Edit: September 18, 2006, 07:59:17 AM by Dave Baranas »

Glenn R

  • Guest
Re: Nested Collections of Classes
« Reply #1 on: September 18, 2006, 08:54:30 PM »
I believe you will need to set the 'nested' attribute on the datarelations to true.

DBARANAS

  • Guest
Re: Nested Collections of Classes
« Reply #2 on: September 19, 2006, 12:47:27 AM »
I believe you will need to set the 'nested' attribute on the datarelations to true.

Thanks Glenn

I tried that and got copies of the nested structure for each new object in the XML file. It does not like that flat/nested file and won't load up.

I am trying another way to get it to work. I made a nested class and am trying to serialize/serialize it. This way I don't care about XML. It works except it can't deserialize the file. I checked the binary file and everything seems to be there. I put a watch on the project object when all classes are added and that looks good too.

I get a null exception when I try to deserialize the file.

Revised Code:
Code: [Select]
<Serializable()> Public Class Project
    Inherits System.Collections.CollectionBase

    Public Function Add(ByVal oBuildings As Buildings) As Boolean
        Try
            List.Add(oBuildings)
            Return True
        Catch E As System.Exception
            Return False
        End Try
    End Function
    <Serializable()> Public Class Buildings
        Inherits System.Collections.CollectionBase

        Public Function Add(ByVal oBuilding As Building) As Boolean
            Try
                List.Add(oBuilding)
                Return True
            Catch E As System.Exception
                Return False
            End Try
        End Function
        <Serializable()> Public Class Storeys
            Inherits System.Collections.CollectionBase

            Public Function Add(ByVal oStorey As Storey) As Boolean
                Try
                    List.Add(oStorey)
                    Return True
                Catch E As System.Exception
                    Return False
                End Try
            End Function
            <Serializable()> Public Class Slabs
                Inherits System.Collections.CollectionBase
                Public Function Add(ByVal oSlab As Slab) As Boolean
                    Try
                        List.Add(oSlab)
                        Return True
                    Catch E As System.Exception
                        Return False
                    End Try
                End Function
            End Class
        End Class
    End Class
End Class
<Serializable()> Public Class Building
    Inherits System.Collections.CollectionBase

    Private m_iRefNo As Integer
    Private m_sName As String
    Public Property RefNo() As Integer
        Get
            Return m_iRefNo
        End Get
        Set(ByVal value As Integer)
            m_iRefNo = value
        End Set
    End Property
    Public Property Name() As String
        Get
            Return m_sName
        End Get
        Set(ByVal Value As String)
            m_sName = Value
        End Set
    End Property
    Public Function Add(ByVal oStoreys As Project.Buildings.Storeys) As Boolean
        Try
            List.Add(oStoreys)
            Return True
        Catch E As System.Exception
            Return False
        End Try
    End Function
End Class
<Serializable()> Public Class Storey
    Inherits System.Collections.CollectionBase

    Private m_iRefNo As Integer
    Private m_sName As String
    Public Property RefNo() As Integer
        Get
            Return m_iRefNo
        End Get
        Set(ByVal Value As Integer)
            m_iRefNo = Value
        End Set
    End Property
    Public Property Name() As String
        Get
            Return m_sName
        End Get
        Set(ByVal Value As String)
            m_sName = Value
        End Set
    End Property
    Public Function Add(ByVal oWalls As Project.Buildings.Storeys.Slabs) As Boolean
        Try
            List.Add(oWalls)
            Return True
        Catch E As System.Exception
            Return False
        End Try
    End Function
End Class
<Serializable()> Public Class Slab

    Private m_iRefNo As Integer
    Private m_sName As String
    Public Property RefNo() As Integer
        Get
            Return m_iRefNo
        End Get
        Set(ByVal Value As Integer)
            m_iRefNo = Value
        End Set
    End Property
    Public Property Name() As String
        Get
            Return m_sName
        End Get
        Set(ByVal Value As String)
            m_sName = Value
        End Set
    End Property
End Class

Code: [Select]
    Private Sub cmdLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdLoad.Click

        Dim oProject As New Project
        Dim oBuildings As New Project.Buildings
        Dim oStoreys As New Project.Buildings.Storeys
        Dim oSlabs As New Project.Buildings.Storeys.Slabs

        oProject.Add(oBuildings)
        Dim oBuilding As New Building
        oBuildings.Add(oBuilding)

        oBuilding.Add(oStoreys)
        Dim oStorey As New Storey
        oStoreys.Add(oStorey)

        oStorey.Add(oSlabs)
        Dim oSlab As New Slab
        oSlabs.Add(oSlab)

        Dim bf As New Formatters.Binary.BinaryFormatter()
        Dim fs As New IO.FileStream("c:\Projects.dat", IO.FileMode.Create)
        bf.Serialize(fs, oProject)
        fs.Close()
        fs = Nothing
        bf = Nothing

        Dim bf1 As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
        Dim fs1 As New IO.FileStream("c:\Projects.dat", IO.FileMode.Open)
        oProject = DirectCast(bf.Deserialize(fs1), Project)
        fs1.Close()
        fs1 = Nothing
        bf1 = Nothing

    End Sub

DBARANAS

  • Guest
Re: Nested Collections of Classes
« Reply #3 on: September 19, 2006, 03:33:55 AM »
found a mistake with bf and got past the exception being thrown

Now it steps through OK but does not really deserialize as I change values before  the write, reset them and do the read.

Oh so close

Code: [Select]
    Private Sub cmdLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdLoad.Click

        Dim oProject As New Project
        Dim oBuildings As New Project.Buildings
        Dim oStoreys As New Project.Buildings.Storeys
        Dim oSlabs As New Project.Buildings.Storeys.Slabs

        oProject.Add(oBuildings)
        Dim oBuilding As New Building
        oBuildings.Add(oBuilding)

        oBuilding.Add(oStoreys)
        Dim oStorey As New Storey
        oStoreys.Add(oStorey)

        oStorey.Add(oSlabs)
        Dim oSlab As New Slab
        oSlabs.Add(oSlab)

        oSlab.Name = "test"
        oSlab.RefNo = 55
        Dim bf As New Formatters.Binary.BinaryFormatter()
        Dim fs As New IO.FileStream("c:\Projects.dat", IO.FileMode.Create)
        bf.Serialize(fs, oProject)
        bf = Nothing
        fs.Close()

        oSlab.Name = ""
        oSlab.RefNo = 44

        Dim bf1 As New Formatters.Binary.BinaryFormatter()
        Dim fs1 As New IO.FileStream("c:\Projects.dat", IO.FileMode.Open)
        oProject = DirectCast(bf1.Deserialize(fs1), Project)
        fs = Nothing
        bf1 = Nothing

    End Sub

DBARANAS

  • Guest
Re: Nested Collections of Classes Working!!
« Reply #4 on: September 19, 2006, 04:52:02 AM »
Got it working by adding a ref to the parent class in the child class(s) constructors.

I wasn't even adding this to fix what was wrong but by doing this it fixed the problem. I really like that feature because now a child class can drill up the hierarchy and I can delete tons of properties I used to have to manage in child classes. Gotta love OOP :lol:
Anyway I hope this might be useful as a way to structure an app. That IFC object model that got me thinking this way is great and I think it should be the way to go since it evolved over years of work and encompasses every imaginable aspect of a building model.

Here is what worked

VB

Code: [Select]
<Serializable()> Public Class Project
    Inherits System.Collections.CollectionBase

    Public Function Add(ByVal oBuildings As Buildings) As Boolean
        Try
            List.Add(oBuildings)
            Return True
        Catch E As System.Exception
            Return False
        End Try
    End Function
    <Serializable()> Public Class Buildings
        Inherits System.Collections.CollectionBase

        Public Function Add(ByVal oBuilding As Building) As Boolean
            Try
                List.Add(oBuilding)
                Return True
            Catch E As System.Exception
                Return False
            End Try
        End Function
        <Serializable()> Public Class Storeys
            Inherits System.Collections.CollectionBase

            Public Function Add(ByVal oStorey As Storey) As Boolean
                Try
                    List.Add(oStorey)
                    Return True
                Catch E As System.Exception
                    Return False
                End Try
            End Function
            <Serializable()> Public Class Slabs
                Inherits System.Collections.CollectionBase
                Public Function Add(ByVal oSlab As Slab) As Boolean
                    Try
                        List.Add(oSlab)
                        Return True
                    Catch E As System.Exception
                        Return False
                    End Try
                End Function
            End Class
        End Class
    End Class
End Class
<Serializable()> Public Class Building
    Inherits System.Collections.CollectionBase

    Private m_iRefNo As Integer
    Private m_sName As String
    Public Property RefNo() As Integer
        Get
            Return m_iRefNo
        End Get
        Set(ByVal value As Integer)
            m_iRefNo = value
        End Set
    End Property
    Public Property Name() As String
        Get
            Return m_sName
        End Get
        Set(ByVal Value As String)
            m_sName = Value
        End Set
    End Property
    Public Function Add(ByVal oStoreys As Project.Buildings.Storeys) As Boolean
        Try
            List.Add(oStoreys)
            Return True
        Catch E As System.Exception
            Return False
        End Try
    End Function
End Class
<Serializable()> Public Class Storey
    Inherits System.Collections.CollectionBase

    Private m_iRefNo As Integer
    Private m_sName As String
    Private ReadOnly m_Building As Building
    Public Property RefNo() As Integer
        Get
            Return m_iRefNo
        End Get
        Set(ByVal Value As Integer)
            m_iRefNo = Value
        End Set
    End Property
    Public Property Name() As String
        Get
            Return m_sName
        End Get
        Set(ByVal Value As String)
            m_sName = Value
        End Set
    End Property
    Public Function Add(ByVal oSlabs As Project.Buildings.Storeys.Slabs) As Boolean
        Try
            List.Add(oSlabs)
            Return True
        Catch E As System.Exception
            Return False
        End Try
    End Function
    Public Sub New(ByVal Building As Building)
        m_Building = Building
    End Sub
End Class
<Serializable()> Public Class Slab

    Private m_iRefNo As Integer
    Private m_sName As String
    Private ReadOnly m_Storey As Storey
    Public Property RefNo() As Integer
        Get
            Return m_iRefNo
        End Get
        Set(ByVal Value As Integer)
            m_iRefNo = Value
        End Set
    End Property
    Public Property Name() As String
        Get
            Return m_sName
        End Get
        Set(ByVal Value As String)
            m_sName = Value
        End Set
    End Property
    Public Sub New(ByVal Storey As Storey)
        m_Storey = Storey
    End Sub
End Class


Code: [Select]
    Private Sub cmdLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdLoad.Click

        Dim oProject As New Project
        Dim oBuildings As New Project.Buildings
        Dim oStoreys As New Project.Buildings.Storeys
        Dim oSlabs As New Project.Buildings.Storeys.Slabs

        oProject.Add(oBuildings)
        Dim oBuilding As New Building
        oBuildings.Add(oBuilding)

        oBuilding.Add(oStoreys)
        Dim oStorey As New Storey(oBuilding)
        oStoreys.Add(oStorey)

        oStorey.Add(oSlabs)
        Dim oSlab As New Slab(oStorey)
        oSlabs.Add(oSlab)

        oSlab.Name = "test"
        oSlab.RefNo = 55
        oStorey.Name = "svsavaxsvs"
        oStorey.RefNo = 123
        Dim bf As New Formatters.Binary.BinaryFormatter()
        Dim fs As New IO.FileStream("c:\Projects.dat", IO.FileMode.Create)
        bf.Serialize(fs, oProject)
        bf = Nothing
        fs.Close()

        oSlab.Name = ""
        oSlab.RefNo = 44
        oStorey.Name = ""
        oStorey.RefNo = 33

        Dim bf1 As New Formatters.Binary.BinaryFormatter()
        Dim fs1 As New IO.FileStream("c:\Projects.dat", IO.FileMode.Open)
        oProject = DirectCast(bf1.Deserialize(fs1), Project)
        fs = Nothing
        bf1 = Nothing

    End Sub

C#


Code: [Select]
[Serializable()]
public class Project : System.Collections.CollectionBase
{

public bool Add(Buildings oBuildings)
{
try
{
List.Add(oBuildings);
return true;
}
catch (System.Exception E)
{
return false;
}
}
[Serializable()]
public class Buildings : System.Collections.CollectionBase
{

public bool Add(Building oBuilding)
{
try
{
List.Add(oBuilding);
return true;
}
catch (System.Exception E)
{
return false;
}
}
[Serializable()]
public class Storeys : System.Collections.CollectionBase
{

public bool Add(Storey oStorey)
{
try
{
List.Add(oStorey);
return true;
}
catch (System.Exception E)
{
return false;
}
}
[Serializable()]
public class Slabs : System.Collections.CollectionBase
{
public bool Add(Slab oSlab)
{
try
{
List.Add(oSlab);
return true;
}
catch (System.Exception E)
{
return false;
}
}
}
}
}
}
[Serializable()]
public class Building : System.Collections.CollectionBase
{

private int m_iRefNo;
private string m_sName;
public int RefNo
{
get
{
return m_iRefNo;
}
set
{
m_iRefNo = value;
}
}
public string Name
{
get
{
return m_sName;
}
set
{
m_sName = value;
}
}
public bool Add(Project.Buildings.Storeys oStoreys)
{
try
{
List.Add(oStoreys);
return true;
}
catch (System.Exception E)
{
return false;
}
}
}

[Serializable()]
public class Storey : System.Collections.CollectionBase
{

private int m_iRefNo;
private string m_sName;
private readonly Building m_Building;
public int RefNo
{
get
{
return m_iRefNo;
}
set
{
m_iRefNo = value;
}
}
public string Name
{
get
{
return m_sName;
}
set
{
m_sName = value;
}
}
public bool Add(Project.Buildings.Storeys.Slabs oSlabs)
{
try
{
List.Add(oSlabs);
return true;
}
catch (System.Exception E)
{
return false;
}
}
public Storey(Building Building)
{
m_Building = Building;
}
}
[Serializable()]
public class Slab
{

private int m_iRefNo;
private string m_sName;
private readonly Storey m_Storey;
public int RefNo
{
get
{
return m_iRefNo;
}
set
{
m_iRefNo = value;
}
}
public string Name
{
get
{
return m_sName;
}
set
{
m_sName = value;
}
}
public Slab(Storey Storey)
{
m_Storey = Storey;
}
}


Code: [Select]
//TODO: INSTANT C# TODO TASK: Insert the following converted event handlers at the end of the 'InitializeComponent' method for forms or into a constructor for other classes:
cmdLoad.Click += new System.EventHandler(cmdLoad_Click);

private void cmdLoad_Click(object sender, System.EventArgs e)
{

Project oProject = new Project();
Project.Buildings oBuildings = new Project.Buildings();
Project.Buildings.Storeys oStoreys = new Project.Buildings.Storeys();
Project.Buildings.Storeys.Slabs oSlabs = new Project.Buildings.Storeys.Slabs();

oProject.Add(oBuildings);
Building oBuilding = new Building();
oBuildings.Add(oBuilding);

oBuilding.Add(oStoreys);
Storey oStorey = new Storey(oBuilding);
oStoreys.Add(oStorey);

oStorey.Add(oSlabs);
Slab oSlab = new Slab(oStorey);
oSlabs.Add(oSlab);

oSlab.Name = "test";
oSlab.RefNo = 55;
oStorey.Name = "svsavaxsvs";
oStorey.RefNo = 123;
Formatters.Binary.BinaryFormatter bf = new Formatters.Binary.BinaryFormatter();
IO.FileStream fs = new IO.FileStream("c:\\Projects.dat", IO.FileMode.Create);
bf.Serialize(fs, oProject);
bf = null;
fs.Close();

oSlab.Name = "";
oSlab.RefNo = 44;
oStorey.Name = "";
oStorey.RefNo = 33;

Formatters.Binary.BinaryFormatter bf1 = new Formatters.Binary.BinaryFormatter();
IO.FileStream fs1 = new IO.FileStream("c:\\Projects.dat", IO.FileMode.Open);
oProject = (Project)(bf1.Deserialize(fs1));
fs = null;
bf1 = null;

}


Draftek

  • Guest
Re: Nested Collections of Classes
« Reply #5 on: September 19, 2006, 08:01:58 AM »
Intersting and thanks for sharing.

I'm currently starting a similar project in C# to build Store Front objects. I was thinking similar using the collection classes by utilizing the parent object as a DLO (Day Light Opening) which would contain other DLO's, Frame members and Glazing members. The Entire elevation would be a DLO with children, and so on.. Much like treeview nodes.

That way, I can use a recursive function to extract, draw, etc. on the object.

Still working on how to sync and store the autocad related geometry with the data related info. I'm also thinking of using an external XML file and / or xdata or custom object (not entity).

DBARANAS

  • Guest
Re: Nested Collections of Classes
« Reply #6 on: September 26, 2006, 04:12:41 AM »
Having tried to implement the nested classes way I discovered too many pitfalls to that approach. I came up with a better way that is way simpler but gives the same results. I pass the parent object as a parameter when creating a child object. This way I can drill up from the child through all the parent objects and not have to have copies of redundant properties propogate through the classes.

Things are more loosely connected but yet still related. I was too eager to find a way to model a top down hierarchy and made things too complicated going the nested route.

Code: [Select]
<Serializable()> Public Class _Slab
    Inherits CollectionBase

    Private _RefNo As Integer
    Private _Name As String
    Private ReadOnly _Storey As _Storey
    Public Property RefNo() As Integer
        Get
            Return _RefNo
        End Get
        Set(ByVal Value As Integer)
            _RefNo = Value
        End Set
    End Property
    Public Property Name() As String
        Get
            Return _Name
        End Get
        Set(ByVal Value As String)
            _Name = Value
        End Set
    End Property
    Public Sub New(ByVal Storey As _Storey)
        _Storey = Storey
    End Sub
End Class


DBARANAS

  • Guest
Re: Nested Collections of Classes - Update
« Reply #7 on: October 05, 2006, 02:33:25 AM »
Things are going good now.

Structuring the app this way lends itself nicely with aTreeView/PropertyGrid GUI scheme. I just want to show how it is coming together and how the GUI chores can go away when doing it this way.

Code: [Select]
    Friend Sub InitializeTreeView()

        Tree.ImageList = ImageList1
        Tree.BeginUpdate()
        Tree.Nodes.Clear()
        With ImageList1.Images
            .Add(New Drawing.Bitmap(My.Resources.help_book.ToBitmap)) '0
            .Add(New Drawing.Bitmap(My.Resources.help_obook.ToBitmap)) '1
            .Add(New Drawing.Bitmap(My.Resources.ball_glass_blueS.ToBitmap)) '2
            .Add(New Drawing.Bitmap(My.Resources.ball_glass_greenS.ToBitmap)) '3
            .Add(New Drawing.Bitmap(My.Resources.ball_glass_redS.ToBitmap)) '4
            .Add(New Drawing.Bitmap(My.Resources.ball_glass_yellowS.ToBitmap)) '5
            .Add(New Drawing.Bitmap(My.Resources.square_blueS.ToBitmap)) '6
            .Add(New Drawing.Bitmap(My.Resources.square_greenS.ToBitmap)) '7
            .Add(New Drawing.Bitmap(My.Resources.square_redS.ToBitmap)) '8
            .Add(New Drawing.Bitmap(My.Resources.square_yellowS.ToBitmap)) '9
            .Add(New Drawing.Bitmap(My.Resources.triangle_blueS.ToBitmap)) '10
            .Add(New Drawing.Bitmap(My.Resources.triangle_greenS.ToBitmap)) '11
            .Add(New Drawing.Bitmap(My.Resources.triangle_redS.ToBitmap)) '12
            .Add(New Drawing.Bitmap(My.Resources.triangle_yellowS.ToBitmap)) '13
        End With

        For Each Project As _Project In Projects
            Tree.Nodes.Add(Project.Name, Project.Name, 0, 1)
            For Each Building As _Building In Buildings
                If Building.Project.Index = Project.Index Then
                    Tree.Nodes(Project.Name).Nodes.Add(Building.Name, Building.Name, 2, 2)
                End If
                For Each Storey As _Storey In Storeys
                    If Storey.Building.Index = Building.Index Then
                        Tree.Nodes(Project.Name).Nodes(Building.Name).Nodes.Add(Storey.Name, Storey.Name, 3, 3)
                    End If
                    For Each Wall As _Wall In Walls
                        If Wall.Storey.Index = Storey.Index Then
                            Tree.Nodes(Project.Name).Nodes(Building.Name).Nodes(Storey.Name).Nodes.Add(Wall.Name, Wall.Name, 4, 4)
                            For Each Window As _Window In Windows
                                If Window.Wall.Index = Wall.Index Then
                                    Tree.Nodes(Project.Name).Nodes(Building.Name).Nodes(Storey.Name).Nodes(Wall.Name).Nodes.Add(Window.Name, Window.Name, 10, 10)
                                End If
                            Next
                            For Each Door As _Door In Doors
                                If Door.Wall.Index = Wall.Index Then
                                    Tree.Nodes(Project.Name).Nodes(Building.Name).Nodes(Storey.Name).Nodes(Wall.Name).Nodes.Add(Door.Name, Door.Name, 11, 11)
                                End If
                            Next
                            For Each BeamPocket As _BeamPocket In BeamPockets
                                If BeamPocket.Wall.Index = Wall.Index Then
                                    Tree.Nodes(Project.Name).Nodes(Building.Name).Nodes(Storey.Name).Nodes(Wall.Name).Nodes.Add(BeamPocket.Name, BeamPocket.Name, 12, 12)
                                End If
                            Next
                            For Each Partition As _Partition In Partitions
                                If Partition.Wall.Index = Wall.Index Then
                                    Tree.Nodes(Project.Name).Nodes(Building.Name).Nodes(Storey.Name).Nodes(Wall.Name).Nodes.Add(Partition.Name, Partition.Name, 13, 13)
                                End If
                            Next
                        End If
                    Next
                Next
            Next
        Next

        Tree.EndUpdate()

    End Sub


Draftek

  • Guest
Re: Nested Collections of Classes
« Reply #8 on: October 05, 2006, 08:17:02 AM »
cool! Love the palette design. I may use that.

I'm doing very similar with the parent / child relationship, here is the skeleton of my dlo object:

Code: [Select]
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace EFCO.ACAD.Generators
{
    /// <summary>
    /// FrameSide enum
    /// </summary>
    public enum FrameSide :int { LeftJamb, RightJamb, Head, Sill }
    // The dlo object - this is the main object of the Mark
    // It will include 4 points, 0-4 sides and a glazing object
    public class DLO
    {
#region Private Variables
        // the four corner points - ll (lower left)
        private Point _ll;
        // lr (lower right)
        private Point _lr;
        // ul (upper right)
        private Point _ur;
        // ul (upper left)
        private Point _ul;
        // collection of children
        DLOCollection _dlos;
        private Frame[] _Frames;
        // for testing
        public string Name;
        // the parent dlo
        private DLO _parent;
#endregion

#region Properties
        public Point ll
        {
            get { return _ll; }
            set { _ll = value; }
        }
        public Point lr
        {
            get { return _lr; }
            set { _lr = value; }
        }
        public Point ur
        {
            get { return _ur; }
            set { _ur = value; }
        }
        public Point ul
        {
            get { return _ul; }
            set { _ul = value; }
        }
        // this would be the children
        public DLOCollection dlos
        {
            get { return _dlos; }
            set { _dlos = value; }
        }
        public DLO parent
        {
            get { return _parent; }
            set { _parent = value; }
        }
#endregion
        // default constructor
        public DLO()
        {
            // set the children collection, thier parent object
            _dlos = new DLOCollection();
            _dlos.Parent = this;
            // and the frames object array
            _Frames = new Frame[3];
        }

        // constructor with the 4 corner points
        // note: Calls the default constructor
        public DLO(DLO parent, Point LL, Point LR, Point UR, Point UL):this()
        {
            this._ll = LL;
            this._lr = LR;
            this._ur = UR;
            this._ul = UL;
        }

    }// end of the DLO Class

    // the point object to be used as a placeholder for the x, y and z
    public struct Point
    {
        public double x;
        public double y;
        public double z;

        // A constructor
        public Point(double X, double Y, double Z)
        {
            this.x = X;
            this.y = Y;
            this.z = Z;
        }
    }

    // this is merely the strong typed collection class of the
    // dlo object which is the children collection
    public class DLOCollection : CollectionBase
    {
        // the parent object to be passed on each add
        private DLO _parent;
        internal DLO Parent
        {
            //get { return _parent; }
            set { _parent = value; }
        }
        public int Add(DLO dlo)
        {
            dlo.parent = _parent;
            return List.Add(dlo);
        }
        public void Remove(DLO dlo)
        {
            List.Remove(dlo);
        }
        public DLO this[int index]
        {
            get { return (DLO)List[index]; }
            set { List[index] = value; }
        }
    }
}