public ConditionsController(IConditionService conditionService)
        {
            _initialCondition = new ConditionExpressionTree();
            var conditions = new DynamicExpression[] { new ConditionAgeIs(), new ConditionGenderIs(), new ConditionFirstNameIs(), new ConditionLastNameIs(), new ConditionOrdersIs() }.ToList();
            var rootBlock = new BlockConditionAndOr { AvailableChildren = conditions };
            _initialCondition.Children = new DynamicExpression[] { rootBlock };

            _conditionService = conditionService;
        }
        public IHttpActionResult SaveCondition(ConditionExpressionTree conditionTree)
        {
            //convert passed condition tree to Condition object
            var condition = conditionTree.ToCondition(Guid.NewGuid().ToString());

            //save it to the storage
            _conditionService.Add(condition);
            return Ok(condition);
        }
        public IHttpActionResult CustomersByConditions(ConditionExpressionTree conditions)
        {
            //get customers from repository
            var customers = _customerRepository.Customers;

            if (conditions != null)
            {
                //compile expression. note: you can now serialize it to save in repository
                var compiledExpression = conditions.GetConditionExpression().Compile();

                //filter customers: create context from customer data and pass it to the compiled expression
                customers = customers.Where(customer => compiledExpression(customer.ToEvaluationContext()));
            }

            return Ok(customers);
        }
        public static ConditionExpressionTree ToInitialCondition(this ConditionExpressionTree deserializedCondition, ConditionExpressionTree initial)
        {
            //Fill AvailableChildren property by copying them from the initial because they not persisted while saving to reduce the serialized object
            var sourceBlocks = (initial as DynamicExpression).Traverse(x => x.Children);
            var targetBlocks = (deserializedCondition as DynamicExpression).Traverse(x => x.Children);
            foreach (var sourceBlock in sourceBlocks)
            {
                foreach (var targetBlock in targetBlocks.Where(x => x.Id == sourceBlock.Id))
                {
                    targetBlock.AvailableChildren = sourceBlock.AvailableChildren;
                }
            }

            //copy available elements from etalon
            deserializedCondition.AvailableChildren = initial.AvailableChildren;

            return deserializedCondition;
        }