[C# version here]
I had the need for a project to quickly design a flexible system that can create boolean flags based on a name and allow for quickly setting/getting the value of them.
My first thought was to implement it as a Dictionary(Of String, Boolean), but I was told that this needed to be serializable, which immediately axed the Dictionary idea as that is -not- serializable [I have tested, if someone finds out otherwise, let me know], so what I decided to do is recreate Dictionary-like attributes using only a List and a Structure.
Along the way, I realized that, as it being a list, I could only access the data using a numerical index:
That's fine and dandy, but that doesn't help me when I'm dealing with names, and calling with names, and searching with names. So, I decided to implement System.Collections.Generic.List(Of FlagCollection.Flag) which gave me some more freedom over what to do with the list.Code:Dim list As New List(Of Flag) Dim F As New Flag F.Name = "XYZ" F.Value = False list.Add(F) Console.WriteLine(list(0).Value)
After working around for awhile, I figured out how to overload the item property, allowing me to change how I searched for data and also what was returned, so the above code could now be transformed:
Both of those code snippets will produce the exact same result with this class now. I'm not sure how useful this class will be to someone, but I decided to post it up anyways; maybe someone will get some use out of it.Code:Dim list As New List(Of Flag) Dim F As New Flag F.Name = "XYZ" F.Value = False list.Add(F) Console.WriteLine(list("XYZ"))
Enough rambling, here's the code. This was run through a translator as I originally coded this in C#:
Code:Imports System.Collections.Generic Imports System.Linq Imports System.Text Namespace FlagCollection ''' <summary> ''' An implementation if a flag collection system using a Generic List from the collections namespace ''' </summary> Public Class FlagCollection Inherits System.Collections.Generic.List(Of FlagCollection.Flag) ''' <summary> ''' An individual structure that contains data for a flag. ''' </summary> <Serializable()> _ Public Structure Flag ''' <summary> ''' Returns or sets the Name of this flag. ''' </summary> Public Property Name() As String Get Return m_Name End Get Set(ByVal value As String) m_Name = Value End Set End Property Private m_Name As String ''' <summary> ''' Returns or sets if the flag is set or not. ''' </summary> Public Property Value() As Boolean Get Return m_Value End Get Set(ByVal value As Boolean) m_Value = Value End Set End Property Private m_Value As Boolean End Structure ''' <summary> ''' Adds a new flag to the flag collection. The return value indicates if the flag was successfully added. ''' </summary> ''' <param name="Name">The name of the flag to add.</param> ''' <param name="Value">The value to set the flag to.</param> Public Overloads Function Add(ByVal Name As String, ByVal Value As Boolean) As Boolean 'Use a bit of LINQ magic. Dim currentFlags = (From _flags In Me Where _flags.Name.Equals(Name) Select _flags).ToList() 'Check If currentFlags.Count.Equals(0) Then Me.Add(New Flag() With { _ .Name = Name, _ .Value = Value _ }) Return True Else Return False End If End Function ''' <summary> ''' Removes a Flag from the collection. The return value indicates if the removal was ''' successful. ''' </summary> ''' <param name="Name">The name of the flag to remove.</param> ''' <returns></returns> Public Overloads Function Remove(ByVal Name As String) As Boolean 'See if it even exists Dim flagList = (From flag In Me Where flag.Name.Equals(Name) Select flag).ToList() 'Check If flagList.Count.Equals(0) Then Return False Else Me.Remove(flagList(0)) Return True End If End Function ''' <summary> ''' Checks to see if a flag exists. ''' </summary> ''' <param name="Name">The name of the flag to check.</param> ''' <returns></returns> Public Overloads Function Exists(ByVal Name As String) As Boolean Return (From f In Me Where f.Name.Equals(Name) Select f).ToList().Count.Equals(1) End Function ''' <summary> ''' Returns the value of a flag. ''' </summary> ''' <param name="Name">The name of the flag to return.</param> ''' <exception cref="FlagNotFoundException">When thrown, the flag name will be passed.</exception> ''' <returns>Returns the value of the flag.</returns> Public Function GetFlagValue(ByVal Name As String) As Boolean 'LINQ Magic Dim flags = (From flag In Me Where flag.Name.Equals(Name) Select flag).ToList() 'Check If flags.Count.Equals(0) Then Throw New FlagNotFoundException(Name) Else Return flags(0).Value End If End Function ''' <summary> ''' Sets a flag with a new value. ''' </summary> ''' <param name="Name">The name of the flag to set.</param> ''' <param name="newValue">The new value of the flag.</param> ''' <exception cref="FlagNotFoundException">When thrown, the flag name will be passed.</exception> ''' <returns>A true or false indicating if the flag was set properly.</returns> Public Function SetFlagValue(ByVal Name As String, ByVal newValue As Boolean) As Boolean 'LINQ Magic Dim flags = (From flag In Me Where flag.Name.Equals(Name) Select flag).ToList() 'Check If flags.Count.Equals(0) Then Throw New FlagNotFoundException(Name) Else Me.Remove(Name) Me.Add(Name, newValue) Return True End If End Function ''' <summary> ''' Returns or sets the value of the given flag. ''' </summary> ''' <param name="name">The name of the flag.</param> ''' <returns></returns> Default Public Overloads Property Item(ByVal name As String) As Boolean Get Return Me.GetFlagValue(name) End Get Set(ByVal value As Boolean) If Not Me.Exists(name) Then Me.Add(New Flag() With { _ .Name = name, _ .Value = If(Not Object.ReferenceEquals(value, Nothing), value, False) _ }) Else Me.SetFlagValue(name, value) End If End Set End Property ''' <summary> ''' Serializes all current flags to a byte array. ''' </summary> ''' <returns></returns> Public Function Save() As Byte() 'Build a memory-stream Dim ms As New System.IO.MemoryStream() 'Build the serializer Dim bf As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter() 'Go ahead and save all the data bf.Serialize(ms, Me) 'Now get our byte array Dim data As Byte() = ms.ToArray() 'Close the array ms.Close() 'Return the data Return data End Function ''' <summary> ''' Deserializes all data from the byte array to the flags. ''' </summary> ''' <param name="data">The data to de-serialize.</param> Public Sub Load(ByVal data As Byte()) 'Build a memory-stream Dim ms As New System.IO.MemoryStream(data) 'Build the deserializer. Dim bf As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter() 'Get all the data Dim FlagData = bf.Deserialize(ms) 'close the stream ms.Close() 'Clear our current data Me.Clear() 'assign the data Me.AddRange(DirectCast(FlagData, List(Of Flag))) End Sub End Class ''' <summary> ''' This exception is thrown when the given flag does not exist. ''' </summary> Public Class FlagNotFoundException Inherits System.Exception Private _msg As String ''' <summary> ''' The name of the flag being checked. ''' </summary> Public Property Name() As String Get Return m_Name End Get Set(ByVal value As String) m_Name = Value End Set End Property Private m_Name As String Public Overrides ReadOnly Property Message() As String Get Return _msg End Get End Property Public Overrides Function ToString() As String Return String.Format("{0}{1}{2}", Me.Message, Environment.NewLine, Me.StackTrace) 'return base.ToString(); End Function ''' <summary> ''' Creates a new FlagNotFoundException. ''' </summary> ''' <param name="FlagName">The name of the flag.</param> Public Sub New(ByVal FlagName As String) Me.Name = FlagName _msg = String.Format("The flag '{0}' was not found in the collection!", FlagName) End Sub End Class End Namespace


Reply With Quote