[Visual Basic .NET 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<string, bool>, 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<FlagCollection.Flag> which gave me some more freedom over what to do with the list.Code:List<Flag> list = new List<Flag>; Flag F = 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:List<Flag> list = new List<Flag>; Flag F = new Flag(); F.Name = "XYZ"; F.Value = false; list.Add(F); Console.WriteLine(list["XYZ"]);
Enough rambling, here's the code.
Code:using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace FlagCollection { /// <summary> /// An implementation if a flag collection system using a Generic List from the collections namespace /// </summary> public class FlagCollection : System.Collections.Generic.List<FlagCollection.Flag> { /// <summary> /// An individual structure that contains data for a flag. /// </summary> [Serializable] public struct Flag { /// <summary> /// Returns or sets the Name of this flag. /// </summary> public string Name { get; set; } /// <summary> /// Returns or sets if the flag is set or not. /// </summary> public bool Value { get; set; } } /// <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 bool Add(string Name, bool Value) { //Use a bit of LINQ magic. var currentFlags = (from _flags in this where _flags.Name.Equals(Name) select _flags).ToList(); //Check if (currentFlags.Count.Equals(0)) { this.Add(new Flag() { Name = Name, Value = Value }); return true; } else { return false; } } /// <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 bool Remove(string Name) { //See if it even exists var flagList = (from flag in this where flag.Name.Equals(Name) select flag).ToList(); //Check if (flagList.Count.Equals(0)) { return false; } else { this.Remove(flagList[0]); return true; } } /// <summary> /// Checks to see if a flag exists. /// </summary> /// <param name="Name">The name of the flag to check.</param> /// <returns></returns> public bool Exists(string Name) { return (from f in this where f.Name.Equals(Name) select f).ToList().Count.Equals(1); } /// <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 bool GetFlagValue(string Name) { //LINQ Magic var flags = (from flag in this where flag.Name.Equals(Name) select flag).ToList(); //Check if (flags.Count.Equals(0)) { throw new FlagNotFoundException(Name); } else { return flags[0].Value; } } /// <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 bool SetFlagValue(string Name, bool newValue) { //LINQ Magic var flags = (from flag in this where flag.Name.Equals(Name) select flag).ToList(); //Check if (flags.Count.Equals(0)) { throw new FlagNotFoundException(Name); } else { this.Remove(Name); this.Add(Name, newValue); return true; } } /// <summary> /// Returns or sets the value of the given flag. /// </summary> /// <param name="name">The name of the flag.</param> /// <returns></returns> public bool this[string name] { get { return this.GetFlagValue(name); } set { if (!this.Exists(name)) { this.Add(new Flag() { Name = name, Value = !object.ReferenceEquals(value, null) ? value : false }); } else { this.SetFlagValue(name, value); } } } /// <summary> /// Serializes all current flags to a byte array. /// </summary> /// <returns></returns> public byte[] Save() { //Build a memory-stream System.IO.MemoryStream ms = new System.IO.MemoryStream(); //Build the serializer System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); //Go ahead and save all the data bf.Serialize(ms, this); //Now get our byte array byte[] data = ms.ToArray(); //Close the array ms.Close(); //Return the data return data; } /// <summary> /// Deserializes all data from the byte array to the flags. /// </summary> /// <param name="data">The data to de-serialize.</param> public void Load(byte[] data) { //Build a memory-stream System.IO.MemoryStream ms = new System.IO.MemoryStream(data); //Build the deserializer. System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); //Get all the data var FlagData = bf.Deserialize(ms); //close the stream ms.Close(); //Clear our current data this.Clear(); //assign the data this.AddRange((List<Flag>)FlagData); } } /// <summary> /// This exception is thrown when the given flag does not exist. /// </summary> public class FlagNotFoundException : System.Exception { string _msg; /// <summary> /// The name of the flag being checked. /// </summary> public string Name { get; set; } public override string Message { get { return _msg; } } public override string ToString() { return string.Format("{0}{1}{2}", this.Message, Environment.NewLine, this.StackTrace); //return base.ToString(); } /// <summary> /// Creates a new FlagNotFoundException. /// </summary> /// <param name="FlagName">The name of the flag.</param> public FlagNotFoundException(string FlagName) { this.Name = FlagName; _msg = string.Format("The flag '{0}' was not found in the collection!", FlagName); } } }


Reply With Quote