Exemplo n.º 1
0
        /// <summary>
        /// Implements the Find method defined by the IBehavior interface. Finds the data
        /// represented by a given find type and extra parameters in a way that allows
        /// behaviors support
        /// </summary>
        /// <param name="type">The type. Changing the type modifies the way the find is performed.
        /// Each type correspond to a custom finder method. For more info on custom finders methods,
        /// see the comments for the InitCustomFinders method of this class. For a concrete example of
        /// a custom finder being defined, see the EFBusiness class</param>
        /// <param name="parameters">Custom parameters. Not used by default, but can be used
        /// to pass special parameters to custom finders to further customize their functionality</param>
        /// <returns>An IQueryable that contains the results of the Find</returns>
        public IQueryable <T> Find(string type = "all", BusinessParameters parameters = null)
        {
            IQueryable <T> results;

            // Call the BeforeFind method of any attached behaviors (if there are any)
            foreach (FindBehaviorDelegate <T> bf in _beforeFinds)
            {
                bf(type, parameters);
            }

            // Execute the custom finder method corresponding the type passed as a parameter.
            // This call perfomrs the actual find functionality
            if (_finds.Keys.Contains(type))
            {
                results = _finds[type](parameters);
            }
            else
            {
                throw new Exception("Attempted to use a non defined find type on a behaviorable business");
            }


            // Call the AfterFind method of any attached behaviors. The AfterFind
            // can then modify the results of the Find if necessary
            foreach (FindBehaviorDelegate <T> bf in _afterFinds)
            {
                results = bf(type, parameters, results);
            }

            return(results as IQueryable <T>);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Implements the Save method defined by the IBusiness interface. Create or update data in the storage solution in
        /// a way that supports behavior
        /// </summary>
        /// <param name="toSave">The data that will be saved</param>
        /// <param name="parameters">Custom parameters. Not used by default, but can be used
        /// to pass special parameters to extended Save methods to further customize their functionality</param>
        /// <returns>True if the save operation succeeded, else false</returns>
        public bool Save(T toSave, BusinessParameters parameters = null)
        {
            // Call the BeforeSave method of any attached behaviors (if there are any)
            bool interruptSave = false;

            foreach (SaveBehaviorDelegate <T> bs in _beforeSaves)
            {
                bool?result = bs(toSave, parameters);
                if (result == false)
                {
                    // if the BeforeSave method of the current behavior returned false, the
                    //current save operation is cancelled. Every BeforeSave calls on any behaviors
                    // attached after the current one will not execute. None of the AfterSaves defined
                    // on attached behaviors will execute.
                    return(false);
                }
                else if (result == null)
                {
                    //If the BeforeSave Method returned null, the save wil be "soft" cancelled. This means the data
                    //isn't saved in the normal way, but the BeforeSave of behaviors attached to the business
                    //after the current one will still be executed. The AfterSave of attached behaviors will also
                    // be executed (unless another BeforeSave further down the line returns false)
                    interruptSave = true;
                }
            }

            //If the save hasn't been interrupted be a BeforeSave returning null, perform the save
            if (!interruptSave)
            {
                if (!SaveHelper(toSave, parameters))
                {
                    // Save failed, return false
                    return(false);
                }
            }

            // Call the AfterSave method of any attached behaviors (if there are any)
            interruptSave = false;
            foreach (SaveBehaviorDelegate <T> asd in _afterSaves)
            {
                bool?success = asd(toSave, parameters);

                if (success == false)
                {
                    // if the AfterSave method of the current behavior returned false, the Save method ends
                    // here. In other words, the AfterSave method for the behaviors attached after the current one
                    // will not be executed.
                    return(false);
                }
                else if (success == null)
                {
                    // if the AfterSave method of the current behavior returned null, the other AfterSave for behaviors
                    // attached after the current one are still executed, however the Save method will return false instead
                    // of true as if the Save failed.
                    interruptSave = true;
                }
            }

            return(interruptSave ? false : true);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Obtains a value stored deeply into an hiarchy of BusinessParameters objects. Takes a serie of keys delimited by
        /// dots, such as this:
        ///
        /// key1.key2.key3
        ///
        /// This means it will find the value stored in key one at the top level. This value should be a second BusinessParameters.
        /// The method will then find the value under key2 in the second BusinessParameters. This should be a third BusinessParameters
        /// object. The method will then find the value under key3 in the third BusinessParameters and return it.
        ///
        /// This simplify fetching deep hiarchical values because there is no need to check wheter all those keys exist manuallyl,
        /// the GetDeepValue methods handles it automatically.
        /// </summary>
        /// <param name="key">A serie of keys delimited by dots.</param>
        /// <returns>The value under the key, or null is such a value does not exists.</returns>
        public dynamic GetDeepValue(string key)
        {
            string[]           keyParts   = key.Split('.');
            BusinessParameters parameters = this;

            // Iterate through every keys separated by dots.
            int max = keyParts.Count() - 1;

            for (int i = 0; i <= max; ++i)
            {
                // Get the value under the current key or null if it doesn't exists
                var tmp = parameters.ContainsKey(keyParts[i]) ? parameters[keyParts[i]] : null;

                if (tmp == null)
                {
                    //The value specified by the dot separated keys does not exist so return null
                    return(null);
                }
                else if (i == max)
                {
                    // This is the last key thus return the value
                    return(tmp);
                }
                else if (tmp is BusinessParameters)
                {
                    // This is before the last key so go one level
                    // deeper in the hiearchie.
                    parameters = tmp;
                }
                else
                {
                    return(null);
                }
            }

            return(null);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Save a value in the hiearchy of BusinessParameters objects using a key made of several dot separated keys.
        /// like as this one:
        ///
        /// key1.key2.key3
        ///
        /// The method starts at the top level. It checks if there is already a second BusinessParameters object under the key1 key.
        /// If not, a second BusinessParameters object is created and set under key one, if there was already one, then the already
        /// existing BusinessParameters is used. Then, the method checks if there is already a third BusinessParameters object
        /// under the key2 keyof the second BusinessParameters object. If not, a third business parameter is created and set under
        /// the key2, if there was already one the existing BusinessParameters is used. Then, the method saves the new value under key3
        /// in the third BusinessParameters.
        ///
        /// The advantage of the static method vs the non static method is that it can start from a null value.
        /// </summary>
        /// <param name="parameters">The top level of the BusinessParameters hiearchy. It can be null. If null, a new
        /// hiearchy is created from scratch</param>
        /// <param name="key">A key made of several dot separted keys</param>
        /// <param name="value">The value that will be set</param>
        /// <returns>The new hiearchy containing the new value</returns>
        static public BusinessParameters SetDeepValue(BusinessParameters parameters, string key, dynamic value)
        {
            // No top of hiearchy passed as a parameter, so start a new hiearchy.
            if (parameters == null)
            {
                parameters = new BusinessParameters();
            }

            string[]           keyParts       = key.Split('.');
            BusinessParameters originalParams = parameters;

            // For every part of the key
            int max = keyParts.Count() - 1;

            for (int i = 0; i <= max; ++i)
            {
                if (i == max)
                {
                    // Last part of the key, set value under the last dot delimited key
                    parameters[keyParts[i]] = value;
                }
                else
                {
                    //If there isn't already a BusinessParameters object under the current key, create a new
                    // one and set it under the current key
                    if (!parameters.ContainsKey(keyParts[i]) || !(parameters[keyParts[i]] is BusinessParameters))
                    {
                        parameters[keyParts[i]] = new BusinessParameters();
                    }

                    // go one level deeper into the hiearchy
                    parameters = parameters[keyParts[i]];
                }
            }

            return(originalParams);
        }
Exemplo n.º 5
0
 public void SetDeepValue(string key, dynamic value)
 {
     BusinessParameters.SetDeepValue(this, key, value);
 }
Exemplo n.º 6
0
 /// <summary>
 /// Inheriting businesses should implement the DeleteHelper method in order to provide the actual deleting functionality.
 /// It is better to implement the delete functionality in this method than by overriding the Delete method because it means
 /// behaviors are treated correctly whithout having to write any extra code. On the other hand, overriding Save can be
 /// useful in cases where behavior support must be unconditionaly removed, or need a special treatment not offered by
 /// GenericBusiness' implementation.
 /// </summary>
 /// <param name="toDelete">The data to be deleted</param>
 /// <param name="parameters">Custom parameters. Not used by default, but can be used
 /// to pass special parameters to extended Delete methods to further customize their functionality</param>
 /// <returns>True if the delete operation succeeded, else false</returns>
 protected abstract bool DeleteHelper(T toDelete, BusinessParameters parameters = null);
Exemplo n.º 7
0
 /// <summary>
 /// Inheriting businesses should implement the SaveHelper method in order to provide the actual saving functionality.
 /// It is better to implement the save functionality in this method than by overriding the Save method because it means
 /// behaviors are treated correctly whithout having to write any extra code. On the other hand, overriding Save can be
 /// useful in cases where behavior support must be unconditionaly removed, or need a special treatment not offered by
 /// GenericBusiness' implementation.
 /// </summary>
 /// <param name="toSave">The data to be saved</param>
 /// <param name="parameters">Custom parameters. Not used by default, but can be used
 /// to pass special parameters to extended Save methods to further customize their functionality</param>
 /// <returns>True if the save operation succeeded, else false</returns>
 protected abstract bool SaveHelper(T toSave, BusinessParameters parameters = null);
Exemplo n.º 8
0
 /// <summary>
 /// Finds the first element obtained by a given find type. This is useful in cases where a find operation can only possibly
 /// return one value
 /// </summary>
 /// <param name="type">The type. Indicates which custom finder will be used by the find method</param>
 /// <param name="parameters"></param>
 /// <returns>Custom parameters. Not used by default, but can be used
 /// to pass special parameters to custom finders to further customize their functionality</returns>
 public virtual T FindFirst(string type, BusinessParameters parameters = null)
 {
     return((this.Find(type, parameters) as IQueryable <T>).FirstOrDefault());
 }