c# - Representing heirarchical enumeration -
i have set of enumeration values (fault codes precise). code 16 bit unsigned integer. looking data structure represent such enumeration. similar question has been asked here: what's best c# pattern implementing hierarchy enum?. hierarchy deeper.
sample enumeration values
current = 0x2000, current_deviceinputside = 0x2100, shorttoearth = 0x2120, shorttoearthinphase1 = 0x2121, shorttoearthinphase2 = 0x2122, shorttoearthinphase3 = 0x2123
use case
when user provides code ui has display equivalent meaning of code hierarchy.
example, if user provides value 0x2121
ui has display short earth in phase 1 in current @ device input side
. best way represent using hierarchical notation: current : deviceinputside : shorttoearth : shorttoearthinphase1
.
competing approaches
have 3 competing approaches represent enumeration:
- create enumeration @ each level of hierarchy. use controller class resolve name.
- store enumeration values in xml , use linq generate meaning of code.
- store enumeration values in xml. during application startup. create singleton instance retrieve meaning. instance contains dictionary populated values xml.
approach 1
enumerations:
enum warncodes { none= 0x000, current = 0x2000 } enum warncodes_current { deviceinputside = 0x2100, deviceoutputside = 0x2200 } enum warncodes_current_deviceinputside { shorttoearth = 0x2120, shortcircuit = 0x2130 } enum warncodes_current_deviceinputside_shorttoearth { inphase1 = 0x2121, inphase2 = 0x2122 }
the controller:
public string getmeaning(int code) { int bitmask = 0xf000; int maskedcode = bitmask & code; stringbuilder meaning = new stringbuilder(); switch (maskedcode) { case warncodes.current: meaning.append("current : "); bitmask = 0xff00; maskedcode = bitmask & code; switch (maskedcode) { case warncodes_current.deviceinputside: meaning.append("current : device input side :"); ... break; } break; ... } }
approach 2
xml store enumeration values looks
<warncodes> <code hex="2000" meaning="current"> <code hex="2100" meaning="current, device input side"> <code hex="2120" meaning="short earth"> <code hex="2121" meaning="short earth in phase l1"/> <code hex="2122" meaning="short earth in phase l2"/> </code> </code> </code> </warncodes>
, method used query codes is: xelement rootelement = xelement.load(settingsfilepath); public string gethierarchicalmeaning(int code) { xelement rootelement = xelement.load(warncodesfilepath); list<string> meanings = new list(); stringbuilder stringbuilder = new stringbuilder(); ienumerable<xelement> elements; elements = el in rootelement.descendants("code") (string)el.attribute("hex") == code.tostring("x") select el; xelement element = elements.first(); while (element.parent != null) { meanings.add(element.attribute("meaning").value); element = element.parent; } meanings.reverse(); foreach (string meaning in meanings) { stringbuilder.appendformat("{0} : ", meaning); } return stringbuilder.tostring().trim().trimend(':').trim(); }
approach 3
xml store enumeration values same in approach 2. dictionary populated xml
getchildren()
.
private dictionary<int, warncodevalue> warncodesdictionary; public void initialize() { xelement rootelement = xelement.load(settingsfilepath); warncodesdictionary = getchildren(rootelement); } private dictionary<int, warncodevalue> getchildren(xelement element) { if (element.descendants().count() > 0) { dictionary<int, warncodevalue> childnodedictionary = new dictionary(); foreach (xelement childelement in element.elements()) { int hex = convert.toint32(childelement.attribute("hex").value, 16); string meaning = childelement.attribute("meaning").value; dictionary<int, warncodevalue> dictionary = getchildren(childelement); warncodevalue warncodevalue; if (dictionary == null) { warncodevalue = new warncodevalue() {meaning = meaning}; } else { warncodevalue = new warncodevalue() {meaning = meaning, childnodes = dictionary}; } childnodedictionary.add(hex, warncodevalue); } return childnodedictionary; } return null; }
the meanings retrieved using gethierarchicalmeaning()
:
public string gethierarchicalmeaning(int code) { stringbuilder stringbuilder = new stringbuilder(); int firstlevel = code & 0xf000; int secondlevel = code & 0xff00; int thirdlevel = code & 0xfff0; if(warncodesdictionary.containskey(firstlevel)) { stringbuilder.appendformat("{0} : ", warncodesdictionary[firstlevel].meaning); if (warncodesdictionary[firstlevel].childnodes != null && warncodesdictionary[firstlevel].childnodes.containskey(secondlevel)) { stringbuilder.appendformat("{0} : ", warncodesdictionary[firstlevel].childnodes[secondlevel].meaning); if (warncodesdictionary[firstlevel].childnodes[secondlevel].childnodes != null && warncodesdictionary[firstlevel].childnodes[secondlevel].childnodes.containskey(thirdlevel)) { stringbuilder.appendformat("{0} : ", warncodesdictionary[firstlevel].childnodes[secondlevel].childnodes[thirdlevel].meaning); if (warncodesdictionary[firstlevel].childnodes[secondlevel].childnodes[thirdlevel].childnodes != null && warncodesdictionary[firstlevel].childnodes[secondlevel].childnodes[thirdlevel].childnodes.containskey(code)) { stringbuilder.appendformat("{0} : ", warncodesdictionary[firstlevel].childnodes[secondlevel].childnodes[thirdlevel].childnodes[code].meaning); } } } } }
the warncodevalue
class:
class warncodevalue { public string meaning { get; set; } public dictionary<int, warncodevalue> childnodes { get; set; } }
questions
- which of above 3 approaches better performance point of view?
- are there other approaches representing enumeration?
- any improvements code?
consider using classes instead of enums, use singleton each value , can use type system build tree, including virtual methods produce error txt etc. (this can sometimes option, can lead lots of problems if not fit well)
Comments
Post a Comment