Subscribe to The Madman Scribblings        RSS Feed
-----

Periodic Table (2 Class 1 XML File+Loads of Exts.)

Icon Leave Comment
In this topic the user is wanting to replicate the periodic table with class, and I though I'll have a go at it.

They are after code the that looks like this.
MyTable.Carbon.AtomicNumber


I decided to store the data on the atomic elements in xml file, so it is easy update.

Class: AtomicElement
Public Class AtomicElement
 Private m_E As XElement
  Public ReadOnly Property _XML() As XElement
  Get
   Return m_E
  End Get
 End Property
  Public Sub New(ByVal element As XElement)
  If element.Name = "ATOM" Then
   m_E = element
  Else
   Throw New NotAnAtomException()
  End If
 End Sub
 Public Overrides Function ToString() As String
  Return String.Format("Name: {1}{0}Symbol: {2}{0}Atomic Number: {3}{0}Atomic Weight: {4}", Environment.NewLine, Me.Name, Me.Symbol, Me.AtomicNumber, Me.AtomicWeight)
 End Function
End Class



Class: PeriodicTable

Public Class PeriodicTable
 Inherits CollectionBase
 Protected mPeriodicTable As XDocument
 Protected m_elements As New List(Of AtomicElement)
 Public Sub New()
  mPeriodicTable = Xdocument.Parse(My.Resources.periodic)
  m_elements = (From e In mPeriodicTable...<ATOM> Let n = New AtomicElement(e) Order By n.AtomicNumber Select n).ToList
 End Sub
 Private Sub New(ByVal ie As IEnumerable(Of AtomicElement))
  m_elements.Clear()
  m_elements.AddRange(ie)
 End Sub
 Public Function OrderByName() As PeriodicTable
  Return New PeriodicTable(From e In mPeriodicTable...<ATOM> Let n = New AtomicElement(e) Order By n.Name Select n)
 End Function
 Public Function OrderByNumber() As PeriodicTable
  Return New PeriodicTable(From e In mPeriodicTable...<ATOM> Let n = New AtomicElement(e) Order By n.AtomicNumber Select n)
 End Function
 Public Function Elements() As IEnumerable(Of AtomicElement)
  Return m_elements.AsEnumerable
 End Function
 Default Public Overloads ReadOnly Property Item(ByVal ElementName As String) As AtomicElement
  Get
   Dim es = From e As AtomicElement In m_elements Select e Where e.Name = ElementName
   If es.Count > 0 Then
	Return es(0)
   Else
	Throw New ElementNotFoundException(String.Format("Element [{0}] not found.", ElementName))
   End If
  End Get
 End Property
 Default Public Overloads ReadOnly Property Item(ByVal AtomicNumber As Integer) As AtomicElement
  Get
   Dim es = From e As AtomicElement In m_elements Select e Where e.AtomicNumber = AtomicNumber
   If es.Count > 0 Then
	Return es(0)
   Else
	Throw New ElementNotFoundException(String.Format("Element with Atomic Number [{0}] not found.", AtomicNumber))
   End If
  End Get
 End Property
 Public Overloads ReadOnly Property Count() As Integer
  Get
   Return Me.m_elements.Count
  End Get
 End Property
 Public Overloads Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of AtomicElement)
  Return Me.m_elements.GetEnumerator
 End Function
End Class


Skip the Exception Class because they are very simple.

The Extension Methods.
The extension methods will add the MyPeriodicTable.Carbon and MyPeriodicTable.Carbon.AtomicNumber

Extensions: AtomicElement
Just a sample so you can see how they are implemented.
Public Module Extensions4AtomicElement
	 <Runtime.CompilerServices.Extension()> _
	Public Function AtomicNumber(ByVal ae As AtomicElement) As Double
		Dim x = ae._XML.<ATOMIC_NUMBER>.Value
		If x Is Nothing Then Return Double.NaN
		Return Double.Parse(x)
	End Function
	 <Runtime.CompilerServices.Extension()> _
	Public Function AtomicVolume(ByVal ae As AtomicElement) As Double
		Dim x = ae._XML.<ATOMIC_VOLUME>.Value
		If x Is Nothing Then Return Double.NaN
		Return Double.Parse(x)
	End Function
	<Runtime.CompilerServices.Extension()> _
	Public Function Name(ByVal ae As AtomicElement) As String
		Return ae._XML.<NAME>.Value
  End Function
	 <Runtime.CompilerServices.Extension()> _
	Public Function Symbol(ByVal ae As AtomicElement) As String
		Return ae._XML.<SYMBOL>.Value
	End Function
'
'
' Etc
'
'
 End Module



Extensions: PeriodicTable
Just a sample so you can see how they are implemented.

Public Module Ext_PeriodicTable
#Region "A's"
 <Runtime.CompilerServices.Extension()> _
Public Function Actinium(ByVal pT As PeriodicTable) As AtomicElement
  Return pT("Actinium")
 End Function
 <Runtime.CompilerServices.Extension()> _
Public Function Aluminum(ByVal pT As PeriodicTable) As AtomicElement
  Return pT("Aluminum")
 End Function
 <Runtime.CompilerServices.Extension()> _
Public Function Americium(ByVal pT As PeriodicTable) As AtomicElement
  Return pT("Americium")
 End Function
 <Runtime.CompilerServices.Extension()> _
Public Function Antimony(ByVal pT As PeriodicTable) As AtomicElement
  Return pT("Antimony")
 End Function
 <Runtime.CompilerServices.Extension()> _
Public Function Argon(ByVal pT As PeriodicTable) As AtomicElement
  Return pT("Argon")
 End Function
 <Runtime.CompilerServices.Extension()> _
Public Function Arsenic(ByVal pT As PeriodicTable) As AtomicElement
  Return pT("Arsenic")
 End Function
 <Runtime.CompilerServices.Extension()> _
Public Function Astatine(ByVal pT As PeriodicTable) As AtomicElement
  Return pT("Astatine")
 End Function
#End Region
'
' Etc for Rest of Alphabet
'



In the finished Dll there is 343 lines of code (288 of them are the extension method.)

All there left to do is update the xml file with the latest information (but that's a project for another day.)

0 Comments On This Entry