public virtual void AddBitCombinations() { //AutoExpand enum into bit combinations //Note: We do this to make choosing the parameters easier and faster (ie: one time hit) //In addition we do this inorder to keep track of each combinations coverage //Must be an Enumerable type if (this.Type == null || !this.Type.IsEnum) { throw new ModelException(this, "BitMask can only be specified on a Enumerable type", null); } //Note: A simple (ripple) counter is the easiest solution // For example, Given 3 bits { A, B, C } the combinations are simply: // A, B, C Value // ------------------- // 0, 0, 0, = 0 (invalid, no bits on) // 0, 0, 1, = 1 // 0, 1, 0, = 2 // 0, 1, 1, = 3 // 1, 0, 0, = 4 // 1, 0, 1, = 5 // 1, 1, 0, = 6 // 1, 1, 1, = 7 ModelValues values = this.Values; Hashtable hash = new Hashtable(); //Automatic Dup collapsing int bits = values.Count; //bits int total = (int)Math.Pow(2, bits); //2^n for (int i = 1; i < total; i++) { int value = 0; //Calculate which bits are on for (int bit = 0; bit < bits; bit++) { int mask = 0x00000001 << bit; if ((i & mask) != 0) { value |= (int)values[bit].Value; } } //Note: We have to covert it back to the enum, inorder to call the method hash[value] = Enum.ToObject(this.Type, value); //Since 0 is skipped } //Update our list of values values.Clear(); foreach (object value in hash.Values) { values.Add(new ModelValue(value)); } }
//Accessors public virtual void SetAttributeValues(ModelRangeAttribute attr) { base.SetAttributeValues(attr); if (attr != null) { _conjunction = attr.Conjunction; //Specified variable if (attr.Variable != null && this.Model != null) { _variable = DetermineVariable(attr.Variable); } //Copy the value array (so modifications don't muck with the original static model) _values.Clear(); _values.Add(attr._values); } }