//WARNING: //Rule: avoid virtual overridable methods in constructors. //Rational: the subclass isn't initialized when execution the below methods. Doing It, frequently result in subclass constructor errors //or unexpected initialization. The order of initialization runs as: base.Constructor -> Hook method -> subclass.Contructor. //Comment: In that scenario (template method in the base constructor class) and different use of the template method pattern, //the child constructor doesn't act as a true initializer, the base class impose some policy for initialization. //Then why code initialization under subclass constructors? The subclasses must adapt to initialization policy of parents //and go with empty constructors or code that does't nullifies the policy. //READ article in my blog https://claudiorivera.net about Template Methods in Constructors. public ConstraintBase(string name, string property, object value, ConstraintOperator op, Type valueType, Type typeToValidate) { _name = name; _property = property; _value = value; _operator = op; _valueType = valueType; _typeToValidate = typeToValidate; _constraintString = SerializePropertiesToConstraintString(); ParseConstraintString(); }
protected override ConstraintBase MakeConstraint(ConstraintOperator op) { //return a contraint based on the operator type switch (op) { case ConstraintOperator.Range: return new XmlRangeConstraint(); case ConstraintOperator.OptionsSet: return new XmlOptionsSetConstraint(); default: return new XmlExactConstraint(); } }
/// <summary> /// Appends the specified operator to the expression by first /// reducing the operator stack and then pushing the new /// operator on the stack. /// </summary> /// <param name="op">The operator to push.</param> public void Append(ConstraintOperator op) { op.LeftContext = lastPushed; if (lastPushed is ConstraintOperator) { SetTopOperatorRightContext(op); } // Reduce any lower precedence operators ReduceOperatorStack(op.LeftPrecedence); ops.Push(op); lastPushed = op; }
/// <summary> /// Resolves this instance, returning a Constraint. If the builder /// is not currently in a resolvable state, an exception is thrown. /// </summary> /// <returns>The resolved constraint</returns> public Constraint Resolve() { if (!IsResolvable) { throw new InvalidOperationException("A partial expression may not be resolved"); } while (!ops.Empty) { ConstraintOperator op = ops.Pop(); op.Reduce(constraints); } return(constraints.Pop()); }
/// <summary> /// Sets the top operator right context. /// </summary> /// <param name="rightContext">The right context.</param> private void SetTopOperatorRightContext(object rightContext) { // Some operators change their precedence based on // the right context - save current precedence. int oldPrecedence = ops.Top.LeftPrecedence; ops.Top.RightContext = rightContext; // If the precedence increased, we may be able to // reduce the region of the stack below the operator if (ops.Top.LeftPrecedence > oldPrecedence) { ConstraintOperator changedOp = ops.Pop(); ReduceOperatorStack(changedOp.LeftPrecedence); ops.Push(changedOp); } }
protected abstract ConstraintBase MakeConstraint(ConstraintOperator op);
/// <summary> /// Appends an operator to the expression and returns the /// resulting expression itself. /// </summary> public ConstraintExpression Append(ConstraintOperator op) { builder.Append(op); return (ConstraintExpression)this; }
public Constraint() { Operator = ConstraintOperator.Equals; Logic = ConstraintLogic.And; }
/// <summary> /// Appends an operator to the expression and returns the /// resulting expression itself. /// </summary> public ConstraintExpression Append(ConstraintOperator op) { builder.Append(op); return((ConstraintExpression)this); }
/// <summary> /// Pushes the specified operator onto the stack. /// </summary> /// <param name="op">The op.</param> public void Push(ConstraintOperator op) { stack.Push(op); }
public XmlRangeConstraint(string name, string property, object value, ConstraintOperator op, Type valueType, Type typeToValidate) : base(name, property, value, op, valueType, typeToValidate) { }