
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseClass.cs

using System;
using Microsoft.Extensions.Logging;
using xCommons.Extensions;
using xExceptions.Constants;

namespace xModels.Base {
    /// <summary>
    /// a Base class which carry required things as a Father for it's childs ...
    /// </summary>
    public abstract class XBaseClass {
        //
        #region Properties ...
        /// <summary>
        /// LogTag which Specified for this class ...
        /// </summary>
        private readonly string LOG_TAG;

        /// <summary>
        /// logger instance ...
        /// </summary>
        private readonly ILogger logger;
        #endregion

        //
        #region Constructor ...
        public XBaseClass (ILoggerFactory loggerFactory) {
            //
            // Preparing Log Tag ...
            LOG_TAG = this.GetType ().Name;

            //
            Type classType = this.GetType ();
            logger = loggerFactory.CreateLogger (classType);
        }
        #endregion

        //
        #region Protected ...
        /// <summary>
        /// Extract Prepared Log MEssage ...
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        protected virtual string GetLogMessage (string message) {
            //
            // Prepare Log Message ...
            message = $"{LOG_TAG} => {message}";
            return message;
        }

        /// <summary>
        /// Logging specific Message ...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="logLevel"></param>
        protected virtual void LogMessage (
            string message,
            LogLevel logLevel = LogLevel.Information
        ) {
            //
            // Validate Args ...
            if (message.IsNullOrEmpty ()) {
                throw XException.InvalidArgs
                    .ToException ();
            }

            //
            // Prepare Log Message ...
            message = GetLogMessage (message);

            //
            // Logging Message ...
            logger.Log (
                message: message,
                logLevel: logLevel
            );
        }

        /// <summary>
        /// Logging specific Message to Console ...
        /// </summary>
        /// <param name="message"></param>
        protected virtual void ConsoleMessage (string message) {
            //
            // Validate Args ...
            if (message.IsNullOrEmpty ()) {
                throw XException.InvalidArgs
                    .ToException ();
            }

            //
            // Prepare Log Message ...
            message = GetLogMessage (message);

            //
            // Logging Message ...
            Console.WriteLine (message);
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseDescriptor.cs

namespace xModels.Base {
    /// <summary>
    /// Descriptors classes Map required data for creating Entities on Seeding time ...
    /// this is a Base Descriptor class ...
    /// </summary>
    public abstract class XBaseDescriptor { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseDto.cs

namespace xModels.Base {
    /// <summary>
    /// DTO - Data Transfer Objects is a kind of classes which Represent Entities ...
    /// this is base Dto class ...
    /// </summary>
    public abstract class XBaseDto { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseEntity.cs

using System.ComponentModel.DataAnnotations;

namespace xModels.Base {
    /// <summary>
    /// Base Entity Class
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class XBaseEntity<T> {
        /// <summary>
        /// Entity Id
        /// </summary>
        /// <value>entity unique id</value>
        [Key]
        [Required]
        public T Id { get; set; }

        /// <summary>
        /// Provided Soft Delete Behaviour ...
        /// </summary>
        /// <value></value>
        public bool Deleted { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseEntityDto.cs

namespace xModels.Base
{
    /// <summary>
    /// Base Entity Related Dto Class ...
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    public abstract class XBaseEntityDto<TKey>
    {
        /// <summary>
        /// Entity Id
        /// </summary>
        /// <value>entity unique id</value>
        public TKey Id { get; set; }

        /// <summary>
        /// Provided Soft Delete Behaviour ...
        /// </summary>
        /// <value></value>
        public bool Deleted { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseGuidIDEntity.cs

using System;

namespace xModels.Base {
    /// <summary>
    /// a BaseEntity Class which has Id of Guid type
    /// </summary>
    public class XBaseGuidIDEntity : XBaseEntity<Guid> { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseGuidIDEntityDto.cs

using System;

namespace xModels.Base
{
    public class XBaseGuidIDEntityDto : XBaseEntityDto<Guid>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseIntIDEntity.cs

using System.ComponentModel.DataAnnotations;

namespace xModels.Base {
    /// <summary>
    /// a BaseEntity Class which has Id of int type
    /// </summary>
    public abstract class XBaseIntIDEntity : XBaseEntity<int> { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseIntIDEntityDto.cs

namespace xModels.Base
{
    public class XBaseIntIDEntityDto : XBaseEntityDto<int>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseLongIDEntity.cs

namespace xModels.Base
{
    public class XBaseLongIDEntity : XBaseEntity<long>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseLongIDEntityDto.cs

namespace xModels.Base
{
    public class XBaseLongIDEntityDto : XBaseEntityDto<long>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseRangeRequest.cs

using System.Collections.Generic;

namespace xModels.Base {
    /// <summary>
    /// Range Request Classes Carry a List of Objects
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class XBaseRangeRequest<T> {
        public IEnumerable<T> Items { get; set; } = new HashSet<T> ();
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseStorableDto.cs

namespace xModels.Base {
    public abstract class XBaseStorableDto<TKey> : XBaseDto {
        public abstract TKey Id { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseStorableDtoEventModel.cs

namespace xModels.Base
{
    public class XBaseStorableDtoEventModel<T>
    {
        public T Model { get; set; }

        public XBaseStorableDtoEventModel(T model)
        {
            Model = model;
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseStoreEvent.cs

using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using xModels.Interfaces;

namespace xModels.Base
{
    public abstract class XBaseStoreEvent<T, TKey> : IXBaseStoreEvents<T, TKey>
    where T : XBaseStorableDto<TKey>
    {
        //
        private readonly ISubject<XBaseStorableDtoEventModel<T>> onAddSubject;
        private readonly ISubject<XBaseStorableDtoEventModel<T>> onUpdateSubject;
        private readonly ISubject<XBaseStorableDtoEventModel<T>> onRemoveSubject;

        //
        private readonly ISubject<XBaseStorableDtoEventModel<IEnumerable<T>>> onAddManySubject;
        private readonly ISubject<XBaseStorableDtoEventModel<IEnumerable<T>>> onUpdateManySubject;
        private readonly ISubject<XBaseStorableDtoEventModel<IEnumerable<T>>> onRemoveManySubject;

        //
        public IObservable<XBaseStorableDtoEventModel<T>> OnAddObservable => onAddSubject.AsObservable();

        public IObservable<XBaseStorableDtoEventModel<T>> OnUpdateObservable => onUpdateSubject.AsObservable();

        public IObservable<XBaseStorableDtoEventModel<T>> OnRemoveObservable => onRemoveSubject.AsObservable();

        //

        public IObservable<XBaseStorableDtoEventModel<IEnumerable<T>>> OnAddManyObservable => onAddManySubject.AsObservable();

        public IObservable<XBaseStorableDtoEventModel<IEnumerable<T>>> OnUpdateManyObservable => onUpdateManySubject.AsObservable();

        public IObservable<XBaseStorableDtoEventModel<IEnumerable<T>>> OnRemoveManyObservable => onRemoveManySubject.AsObservable();

        //
        protected XBaseStoreEvent()
        {
            //
            onAddSubject = new ReplaySubject<XBaseStorableDtoEventModel<T>>(1);
            onUpdateSubject = new ReplaySubject<XBaseStorableDtoEventModel<T>>(1);
            onRemoveSubject = new ReplaySubject<XBaseStorableDtoEventModel<T>>(1);

            //
            onAddManySubject = new ReplaySubject<XBaseStorableDtoEventModel<IEnumerable<T>>>(1);
            onUpdateManySubject = new ReplaySubject<XBaseStorableDtoEventModel<IEnumerable<T>>>(1);
            onRemoveManySubject = new ReplaySubject<XBaseStorableDtoEventModel<IEnumerable<T>>>(1);
        }

        //
        #region Base Actions ...
        public void AddEvent(XBaseStorableDtoEventModel<T> model)
        {
            onAddSubject.OnNext(model);
        }

        public void AddManyEvent(XBaseStorableDtoEventModel<IEnumerable<T>> model)
        {
            onAddManySubject.OnNext(model);
        }

        public void RemoveEvent(XBaseStorableDtoEventModel<T> model)
        {
            onRemoveSubject.OnNext(model);
        }

        public void RemoveManyEvent(XBaseStorableDtoEventModel<IEnumerable<T>> model)
        {
            onRemoveManySubject.OnNext(model);
        }

        public void UpdateEvent(XBaseStorableDtoEventModel<T> model)
        {
            onUpdateSubject.OnNext(model);
        }

        public void UpdateManyEvent(XBaseStorableDtoEventModel<IEnumerable<T>> model)
        {
            onUpdateManySubject.OnNext(model);
        }
        #endregion
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseStringIDEntity.cs

using System;

namespace xModels.Base {
    /// <summary>
    /// a BaseEntity Class which has Id of string type
    /// </summary>
    public class XBaseStringIDEntity : XBaseEntity<string> { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseStringIDEntityDto.cs

namespace xModels.Base
{
    public class XBaseStringIDEntityDto : XBaseEntityDto<string>
    { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Base\XBaseValueContainer.cs

namespace xModels.Base
{
    public class XBaseValueContainer<T>
    {
        public T Value { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XBaseIndexedDto.cs

using xModels.Base;

namespace xModels.Dtos
{
    public class XBaseIndexedDto<T, TKey, TIndex> : XBaseDto
    {
        public T Item { get; set; }
        public TKey Key { get; set; }
        public TIndex Index { get; set; }
    }

    public class XBaseIntIndexedDto<T> : XBaseIndexedDto<T, string, int> { }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XDeviceDto.cs

using xCommons.Constants;
using xModels.Base;

namespace xModels.Dtos {
    public class XDeviceDto : XBaseDto {
        /// <summary>
        /// Operating System
        /// </summary>
        /// <value>device operating system identifier</value>
        public string Os { get; set; }
        /// <summary>
        /// Operating System Version
        /// </summary>
        /// <value>which version of operatin system is in use</value>
        public string OsVersion { get; set; }
        /// <summary>
        /// Device Browser
        /// </summary>
        /// <value>the Browser identifier</value>
        public string Browser { get; set; }
        /// <summary>
        /// Browser Engine Agent
        /// </summary>
        /// <value>browser engine Agent</value>
        public string UserAgent { get; set; }
        /// <summary>
        /// Type of client Device
        /// </summary>
        /// <value>represent device type <see>XDeviceType</see></value>
        public XDeviceType DeviceType { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XFileDto.cs

using System;
using System.ComponentModel.DataAnnotations;
using xCommons.Constants;
using xModels.Base;

namespace xModels.Dtos {
    public partial class XFileDto : XBaseDto {
        [Required]
        public string AuthorId { get; set; }

        public XFileType Type { get; set; }

        [Required]
        [StringLength (255)]
        public string Name { get; set; }

        [StringLength (255)]
        public string Thumb { get; set; }

        [Required]
        [StringLength (255)]
        public string Path { get; set; }

        [StringLength (255)]
        public string ThumbPath { get; set; }

        [Required]
        public DateTime UploadedOn { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XObjectResponseResult.cs

namespace xModels.Dtos {
    /// <summary>
    /// Some Requests Get Object Response Result of Data ...
    /// </summary>
    public struct XObjectResponseResult<T> {

        public XObjectResponseResult (T responseObject, string responseText) {
            this.Object = responseObject;
            this.Text = responseText;
        }

        public T Object { get; }

        public string Text { get; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XPersonDto.cs

using xModels.Base;

namespace xModels.Dtos
{
    /// <summary>
    /// Since in Many Cases we have to Retrieve Specified User's Minimal
    /// Infos for Handle Data Transfering, this Dto is Used ...
    /// </summary>
    public class XPersonDto : XBaseDto
    {
        public string Username { get; set; }
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public string Avatar { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XQuery.cs

using xModels.Base;

namespace xModels.Dtos {
    /// <summary>
    /// Request a Page of Data Based on Query ...
    /// this can used in every Data Providers ...
    /// </summary>
    public class XQuery : XBaseDto {
        /// <summary>
        /// an string for filtering results
        /// </summary>
        /// <value></value>
        public string Filter { get; set; } = null;

        /// <summary>
        /// determines fully load object with it's relational fields or not
        /// </summary>
        /// <value></value>
        public bool ContainsDetail { get; set; } = false;

        /// <summary>
        /// specifiy sorting of items
        /// </summary>
        /// <returns></returns>
        public string SortBy { get; set; } = nameof (XBaseIntIDEntity.Id);

        /// <summary>
        /// specify sorting direction
        /// </summary>
        /// <value></value>
        public bool IsAscending { get; set; } = true;

        /// <summary>
        /// specify page number
        /// </summary>
        /// <value></value>
        public int Page { get; set; } = 1;

        /// <summary>
        /// specify page size
        /// </summary>
        /// <value></value>
        public int PageSize { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XQueryResult.cs

using System.Collections.Generic;
using xModels.Base;

namespace xModels.Dtos {
    /// <summary>
    /// Result of a Requested Page of Data Based on Query ...
    /// this can used in every Data Providers ...
    /// </summary>
    public class XQueryResult<T> : XBaseDto {
        /// <summary>
        /// a collection of items for a page ...
        /// </summary>
        /// <value></value>
        public IEnumerable<T> Items { get; set; }

        /// <summary>
        /// Current Page Number ...
        /// </summary>
        /// <value></value>
        public long Page { get; set; }

        /// <summary>
        /// Current Page Size ...
        /// </summary>
        /// <value></value>
        public long PageSize { get; set; }

        /// <summary>
        /// Total Pages ...
        /// </summary>
        /// <value></value>
        public long TotalPages { get; set; }

        /// <summary>
        /// Total Filtered Items Pages Count ...
        /// </summary>
        /// <value></value>
        public int TotalFilteredPages { get; set; }

        /// <summary>
        /// Total Filtered Items ...
        /// </summary>
        /// <value></value>
        public long TotalFilteredItems { get; set; }

        /// <summary>
        /// Total Exists Items ...
        /// </summary>
        /// <value></value>
        public long TotalItems { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XResourceDto.cs

using System.Collections.Generic;
using xModels.Base;

namespace xModels.Dtos
{
    public class XLocaleResourceDto : XBaseDto
    {
        public string Language { get; set; }
        public string Value { get; set; }
    }

    public class XResourceDto : XBaseDto
    {
        public string Resource { get; set; }
        public IEnumerable<XLocaleResourceDto> Locales { get; set; } = new HashSet<XLocaleResourceDto>();
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Dtos\XValidateRevisionRequest.cs

using System.ComponentModel.DataAnnotations;

namespace xModels.Dtos {
    /// <summary>
    /// in some cases we have to validate a revision of request, this is a model 
    /// which used to request a revision validator ...
    /// </summary>
    public class XValidateRevisionRequest {
        [Required]
        public string Revision { get; set; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Extensions\DIExtensions.cs

using Microsoft.Extensions.DependencyInjection;
using xCommons.Extensions;
using xExceptions.Constants;
using xModels.Base;
using xModels.Interfaces;

namespace xModels.Extensions {
    public static class DIExtensions {
        /// <summary>
        /// Register an Specific Store in DI ...
        /// </summary>
        /// <param name="services">DI service collection ...</param>
        /// <param name="store">an implementation of inetrface of store ...</param>
        /// <param name="lifeTime">service lifetime</param>
        /// <typeparam name="TImplementation">implementation of TType ...</typeparam>
        /// <typeparam name="TType">an inetrface which implements IXBaseStore<TStoreItemDto, TKey></typeparam>
        /// <typeparam name="TStoreItemDto">type of an instance of XBaseStorable<TKey></typeparam>
        /// <typeparam name="TKey">type of key of StorableItem</typeparam>
        /// <returns></returns>
        public static void AddXStore<TImplementation, TType, TStoreItemDto, TKey> (
            this IServiceCollection services,
            TImplementation store,
            ServiceLifetime lifeTime = ServiceLifetime.Singleton
        )
        where TImplementation : TType
        where TType : IXBaseStore<TStoreItemDto, TKey>
            where TStoreItemDto : XBaseStorableDto<TKey> {
                //
                // Validate Args ...
                if (store.IsNull ()) {
                    throw XException.InvalidArgs
                        .ToException ();
                }

                //
                // Register Service in DI ...
                services.Add (new ServiceDescriptor (typeof (TType), typeof (TImplementation), lifeTime));
            }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Extensions\XModelExtensions.cs

using System.Collections.Generic;
using System.Linq;
using xCommons.Extensions;
using xModels.Dtos;

namespace xModels.Extensions
{
    public static class XModelExtensions
    {
        /// <summary>
        /// Check to XDevice instance to be same or not
        /// </summary>
        /// <param name="source"></param>
        /// <param name="dest"></param>
        /// <returns></returns>
        public static bool IsSameAs(this XDeviceDto source, XDeviceDto dest)
        {
            //
            if (source.IsNull() ||
                dest.IsNull())
            {
                return false;
            }

            //
            var isSame = source.Os.ToNormalString() == dest.Os.ToNormalString() &&
                source.OsVersion.ToNormalString() == dest.OsVersion.ToNormalString() &&
                source.Browser.ToNormalString() == dest.Browser.ToNormalString() &&
                source.UserAgent.ToNormalString() == dest.UserAgent.ToNormalString() &&
                source.DeviceType == dest.DeviceType;

            //
            return isSame;
        }

        public static IEnumerable<T> AsEnumerable<T, TKey, TIndex>(
            this IEnumerable<XBaseIndexedDto<T, TKey, TIndex>> source
        )
        {
            return source.Select(i => i.Item);
        }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Interfaces\IXAuditable.cs

using System;

namespace xModels.Interfaces {
    /// <summary>
    /// Some times we need to wrap Entities by some logs or audits ...
    /// this class provide Audit fields for an Auditable Entity ...
    /// </summary>
    public interface IXAuditable {
        string UserAgent { get; }
        string UserIp { get; }
        DateTime TransactionTime { get; }
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Interfaces\IXBaseStore.cs

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
using xModels.Base;

namespace xModels.Interfaces {
    public interface IXBaseStore<T, TKey> where T : XBaseStorableDto<TKey> {
        //
        #region Retrieve ...
        /// <summary>
        /// Retrieve all Exists Items ...
        /// </summary>
        /// <returns></returns>
        Task<IEnumerable<T>> GetAll ();

        /// <summary>
        /// Retrieve specific Item by key ...
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<T> Get (TKey key);

        /// <summary>
        /// retrieve items based on specific condition ...
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        Task<IEnumerable<T>> FindMany (Expression<Func<T, bool>> condition);

        /// <summary>
        /// retrieve item based on specific condition ...
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        Task<T> FindOne (Expression<Func<T, bool>> condition);
        #endregion

        //
        #region Add ...
        /// <summary>
        /// add specific item to Store ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        Task<bool> Add (T item);

        /// <summary>
        /// Add a Collection of Items on Store ...
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        Task<bool> AddMany (XBaseRangeRequest<T> items);
        #endregion

        //
        #region Remove ...
        /// <summary>
        /// Remove an item from store ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        Task<bool> Remove (T item);

        /// <summary>
        /// remove an item by it's Key ...
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<bool> RemoveByKey (TKey key);
        
        /// <summary>
        /// remove a collection of items at once ...
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        Task<bool> RemoveMany(XBaseRangeRequest<T> items);
        #endregion

        //
        #region Update ...
        /// <summary>
        /// Update Exists Item in store ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="propertyWhiteList"></param>
        /// <param name="propertyBlackList"></param>
        /// <param name="propertyValueProviders"></param>
        /// <param name="updateWithNullOrEmptyValues"></param>
        /// <returns></returns>
        Task<T> Update (
            T item,
            ICollection<string> propertyWhiteList = null,
            ICollection<string> propertyBlackList = null,
            ICollection<KeyValuePair<string, Func<T, object>>> propertyValueProviders = null,
            bool updateWithNullOrEmptyValues = false
        );

        /// <summary>
        /// Update a Collection of Exists Items ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="propertyWhiteList"></param>
        /// <param name="propertyBlackList"></param>
        /// <param name="propertyValueProviders"></param>
        /// <param name="updateWithNullOrEmptyValues"></param>
        /// <returns></returns>
        Task<bool> UpdateMany (
            XBaseRangeRequest<T> items,
            ICollection<string> propertyWhiteList = null,
            ICollection<string> propertyBlackList = null,
            ICollection<KeyValuePair<string, Func<T, object>>> propertyValueProviders = null,
            bool updateWithNullOrEmptyValues = false
        );
        #endregion

        //
        #region Exists ...
        /// <summary>
        /// retrieve item(s) exists based on specific condition ...
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        Task<bool> IsExists (Expression<Func<T, bool>> condition);

        /// <summary>
        /// is exists an item by providing it's key ...
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<bool> IsExistsByKey (TKey key);
        #endregion

        //
        #region Count ...
        /// <summary>
        /// Count Exists items ...
        /// </summary>
        /// <returns></returns>
        Task<int> Count ();
        #endregion        
    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Interfaces\IXBaseStoreEvents.cs

using System;
using System.Collections.Generic;
using xModels.Base;

namespace xModels.Interfaces
{
    public interface IXBaseStoreEvents<T, TKey> where T : XBaseStorableDto<TKey>
    {
        //
        void AddEvent(XBaseStorableDtoEventModel<T> model);
        void UpdateEvent(XBaseStorableDtoEventModel<T> model);
        void RemoveEvent(XBaseStorableDtoEventModel<T> model);

        //
        void AddManyEvent(XBaseStorableDtoEventModel<IEnumerable<T>> model);
        void UpdateManyEvent(XBaseStorableDtoEventModel<IEnumerable<T>> model);
        void RemoveManyEvent(XBaseStorableDtoEventModel<IEnumerable<T>> model);

        //
        IObservable<XBaseStorableDtoEventModel<T>> OnAddObservable { get; }
        IObservable<XBaseStorableDtoEventModel<T>> OnUpdateObservable { get; }
        IObservable<XBaseStorableDtoEventModel<T>> OnRemoveObservable { get; }

        //
        IObservable<XBaseStorableDtoEventModel<IEnumerable<T>>> OnAddManyObservable { get; }
        IObservable<XBaseStorableDtoEventModel<IEnumerable<T>>> OnUpdateManyObservable { get; }
        IObservable<XBaseStorableDtoEventModel<IEnumerable<T>>> OnRemoveManyObservable { get; }

    }
}

### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xModels\Providers\XBaseInMemoryStore.cs

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using xCommons.Extensions;
using xModels.Base;
using xModels.Interfaces;

namespace xModels.Providers
{
    public abstract class XBaseInMemoryStore<T, TKey> : IXBaseStore<T, TKey>
        where T : XBaseStorableDto<TKey>
    {
        /// <summary>
        /// this is main store of items ...
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private static ConcurrentBag<T> STORE = new ConcurrentBag<T>();

        //
        private readonly IXBaseStoreEvents<T, TKey> events;

        //
        #region Constructor ...
        protected XBaseInMemoryStore(
            IXBaseStoreEvents<T, TKey> events = null
        )
        {
            this.events = events;
        }
        #endregion

        //
        #region Retrieve ...
        /// <summary>
        /// Retrieve all Exists Items ...
        /// </summary>
        /// <returns></returns>
        public Task<IEnumerable<T>> GetAll()
        {
            //
            var result = STORE.AsEnumerable();
            return Task.FromResult(result);
        }

        /// <summary>
        /// Retrieve specific Item by key ...
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Task<T> Get(TKey key)
        {
            //
            return IsExistsByKey(key)
                .ContinueWith(isExistsTask =>
                {
                    //
                    var isExists = isExistsTask
                        .RunTask();

                    //
                    if (!isExists)
                    {
                        return null;
                    }

                    //
                    try
                    {
                        var result = STORE
                            .FirstOrDefault(i => GetKey(i).Equals(key));
                        return result;
                    }
                    catch
                    {
                        return null;
                    }
                });
        }

        /// <summary>
        /// retrieve items based on specific condition ...
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public Task<IEnumerable<T>> FindMany(Expression<Func<T, bool>> condition)
        {
            //
            // Validate Args ...
            if (condition.IsNull())
            {
                return Task.FromResult(new List<T>().AsEnumerable());
            }

            //
            var whereFunc = condition.Compile();
            var result = STORE.Where(whereFunc);

            //
            return Task.FromResult(result);
        }

        /// <summary>
        /// retrieve item based on specific condition ...
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public Task<T> FindOne(Expression<Func<T, bool>> condition)
        {
            //
            // Validate Args ...
            if (condition.IsNull())
            {
                return null;
            }

            //
            var whereFunc = condition.Compile();
            var result = STORE.FirstOrDefault(whereFunc);

            //
            return Task.FromResult(result);
        }
        #endregion

        //
        #region Add ...
        /// <summary>
        /// add specific item to Store ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public Task<bool> Add(T item)
        {
            //
            // Validate Args ...
            if (item.IsNull() || GetKey(item).IsNull())
            {
                return Task.FromResult(false);
            }

            //
            // Try to add item ...
            return IsExistsByKey(GetKey(item))
                .ContinueWith(isExistsTask =>
                {
                    //
                    // Check item exists in Store or not ...
                    var isExists = isExistsTask.RunTask();
                    if (isExists)
                    {
                        return false;
                    }

                    //
                    // Add Item to Store ...
                    STORE.Add(item);
                    OnAdd(item);

                    //
                    return true;
                });
        }

        /// <summary>
        /// Add a Collection of Items on Store ...
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        public Task<bool> AddMany(XBaseRangeRequest<T> items)
        {
            //
            // Validate Args ...
            if (
                items.IsNull() ||
                !items.Items.HasChild()
            )
            {
                return Task.FromResult(false);
            }

            //
            // Retrieve Must Add Items ...
            var mustAddItems = items.Items
                .Where(i => !GetKey(i)
                    .IsNull() && !STORE
                    .Any(si => GetKey(i).Equals(GetKey(si)))
                );
            if (!mustAddItems.HasChild())
            {
                return Task.FromResult(false);
            }

            //
            // Add Items ...
            try
            {
                //
                mustAddItems
                    .ToList()
                    .ForEach(mi => STORE.Add(mi));

                //
                OnAddMany(mustAddItems);

                //
                return Task.FromResult(true);
            }
            catch
            {
                return Task.FromResult(false);
            }
        }
        #endregion

        //
        #region Remove ...
        /// <summary>
        /// Remove an item from store ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public Task<bool> Remove(T item)
        {
            //
            // Validate Args ...
            if (
                item.IsNull() ||
                !STORE
                .Any(i => GetKey(i)
                    .Equals(GetKey(item)))
            )
            {
                return Task.FromResult(false);
            }

            //
            try
            {
                //
                RemoveItemFromStore(item);
                return Task.FromResult(true);
            }
            catch
            {
                return Task.FromResult(false);
            }
        }

        /// <summary>
        /// remove an item by it's Key ...
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Task<bool> RemoveByKey(TKey key)
        {
            return Get(key)
                .ContinueWith(getTask =>
                {
                    //
                    // retrieve item by it's Key ...
                    var item = getTask
                        .RunTask();

                    //
                    // Check item exists ...
                    if (item.IsNull())
                    {
                        return false;
                    }

                    //
                    // Try to remove item ...
                    var result = false;
                    try
                    {
                        //
                        result = Remove(item)
                            .RunTask();
                    }
                    catch
                    {
                        result = false;
                    }

                    //
                    return result;
                });
        }

        /// <summary>
        /// remove a collection of items at once ...
        /// </summary>
        /// <param name="items"></param>
        /// <returns></returns>
        public Task<bool> RemoveMany(XBaseRangeRequest<T> items)
        {
            //
            // Validate Args ...
            if (
                items.IsNull() ||
                !items.Items.HasChild()
            )
            {
                return Task.FromResult(false);
            }

            //
            var mustRemovedItems = items.Items
                .Where(i => STORE
                    .Any(si => GetKey(si).Equals(GetKey(i)))
                );
            if (!mustRemovedItems.HasChild())
            {
                return Task.FromResult(false);
            }

            //
            try
            {
                //
                RemoveItemsFromStore(mustRemovedItems);
                return Task.FromResult(true);
            }
            catch
            {
                return Task.FromResult(false);
            }
        }
        #endregion

        //
        #region Update ...
        /// <summary>
        /// Update Exists Item in store ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="propertyWhiteList"></param>
        /// <param name="propertyBlackList"></param>
        /// <param name="propertyValueProviders"></param>
        /// <param name="updateWithNullOrEmptyValues"></param>
        /// <returns></returns>
        public Task<T> Update(
            T item,
            ICollection<string> propertyWhiteList = null,
            ICollection<string> propertyBlackList = null,
            ICollection<KeyValuePair<string, Func<T, object>>> propertyValueProviders = null,
            bool updateWithNullOrEmptyValues = false
        )
        {
            return Get(GetKey(item))
                .ContinueWith(getTask =>
                {
                    //
                    var existsItem = getTask
                        .RunTask();

                    //
                    // Validate item Exists ...
                    if (existsItem.IsNull())
                    {
                        return null;
                    }

                    //
                    try
                    {
                        //
                        var updatedItem = existsItem;
                        updatedItem.UpdateData(
                            updateWith: item,
                            propertyWhiteList: propertyWhiteList,
                            propertyBlackList: propertyBlackList,
                            propertyValueProviders: propertyValueProviders,
                            updateWithNullOrEmptyValues: updateWithNullOrEmptyValues,
                            throwExceptionOnFails: true
                        );

                        //
                        RemoveItemFromStore(existsItem);
                        STORE.Add(updatedItem);
                        OnUpdate(item);

                        //
                        return updatedItem;
                    }
                    catch
                    {
                        return null;
                    }
                });
        }

        /// <summary>
        /// Update a Collection of Exists Items ...
        /// </summary>
        /// <param name="items"></param>
        /// <param name="propertyWhiteList"></param>
        /// <param name="propertyBlackList"></param>
        /// <param name="propertyValueProviders"></param>
        /// <param name="updateWithNullOrEmptyValues"></param>
        /// <returns></returns>
        public Task<bool> UpdateMany(
            XBaseRangeRequest<T> items,
            ICollection<string> propertyWhiteList = null,
            ICollection<string> propertyBlackList = null,
            ICollection<KeyValuePair<string, Func<T, object>>> propertyValueProviders = null,
            bool updateWithNullOrEmptyValues = false
        )
        {
            //
            // Validate Args ...
            if (
                items.IsNull() ||
                !items.Items.HasChild()
            )
            {
                return Task.FromResult(false);
            }

            //
            // retrieve must updated items ...
            var mustUpdateItems = items
                .Items
                .Where(i => STORE
                    .Any(
                        si => GetKey(i).Equals(GetKey(si)))
                );
            if (!mustUpdateItems.HasChild())
            {
                return Task.FromResult(false);
            }

            //
            // Do Tasks ...
            var mustUpdateTasks = mustUpdateItems.Select(i => Update(
                i,
                propertyWhiteList: propertyWhiteList,
                propertyBlackList: propertyBlackList,
                propertyValueProviders: propertyValueProviders,
                updateWithNullOrEmptyValues: updateWithNullOrEmptyValues
            ));
            return Task.WhenAll(mustUpdateTasks)
                .ContinueWith(updateTasks =>
                {
                    //
                    var updatedItems = updateTasks
                        .RunTask();

                    //
                    if (!updatedItems.HasChild())
                    {
                        return false;
                    }
                    else
                    {
                        //
                        OnUpdateMany(mustUpdateItems);
                        return true;
                    }
                });
        }
        #endregion

        //
        #region Exists ...
        /// <summary>
        /// retrieve item(s) exists based on specific condition ...
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public Task<bool> IsExists(Expression<Func<T, bool>> condition)
        {
            //
            // Validate Args ...
            if (condition.IsNull())
            {
                return Task.FromResult(false);
            }

            //
            var whereFunc = condition.Compile();
            var result = STORE.Any(whereFunc);

            //
            return Task.FromResult(result);
        }

        /// <summary>
        /// is exists an item by providing it's key ...
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Task<bool> IsExistsByKey(TKey key)
        {
            return Task.Run(() =>
            {
                return STORE.Any(i => GetKey(i).Equals(key));
            });
        }
        #endregion

        //
        #region Count ...
        /// <summary>
        /// Count Exists items ...
        /// </summary>
        /// <returns></returns>
        public Task<int> Count()
        {
            //
            var result = STORE.Count();
            return Task.FromResult(result);
        }
        #endregion

        //
        #region Keys ...
        /// <summary>
        /// set Object Key ...
        /// </summary>
        /// <param name="item"></param>
        /// <param name="id"></param>
        public void SetKey(
            ref T item,
            TKey id
        )
        {
            //
            var props = item.GetType().GetProperties();
            var keyProp = props.FirstOrDefault(p => p.Name == "Id");
            if (keyProp.IsNull())
            {
                return;
            }

            //
            Type t = Nullable.GetUnderlyingType(keyProp.PropertyType) ?? keyProp.PropertyType;
            object safeValue = (id == null) ? null : Convert.ChangeType(id, t);
            keyProp.SetValue(item, safeValue, null);
        }

        /// <summary>
        /// Get Object Key ...
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public TKey GetKey(T item)
        {
            //
            var props = item.GetType().GetProperties();
            var keyProp = props.FirstOrDefault(p => p.Name == "Id");

            //
            var keyString = string.Empty;
            if (keyProp.IsNull())
            {
                keyString = string.Empty;
            }
            else
            {
                keyString = keyProp.GetValue(item).ToString();
            }

            //
            if (keyString.IsNullOrEmpty())
            {
                return default(TKey);
            }

            //
            // Prevent Deserializing issues throug JsonReader ...
            if (keyString.IsGuid() && typeof(TKey) == typeof(Guid))
            {
                return item.Id;
            }

            //
            TKey result;
            try
            {
                result = keyString.FromJSON<TKey>();
            }
            catch
            {
                result = keyString.ConvertTo<TKey>();
            }
            return result;
        }
        #endregion

        //
        #region Private ...
        private void RemoveItemFromStore(T item)
        {
            //
            STORE = new ConcurrentBag<T>(
                STORE.Except(new[] { item })
            );

            //
            OnRemove(item);
        }

        private void RemoveItemsFromStore(IEnumerable<T> items)
        {
            //
            STORE = new ConcurrentBag<T>(
                STORE.Except(items)
            );

            //
            OnRemoveMany(items);
        }

        //
        #region Event Notifiers ...
        private void OnAdd(T item)
        {
            //
            if (!events.IsNull())
            {
                events.AddEvent(new XBaseStorableDtoEventModel<T>(item));
            }
        }
        private void OnUpdate(T item)
        {
            //
            if (!events.IsNull())
            {
                events.UpdateEvent(new XBaseStorableDtoEventModel<T>(item));
            }
        }

        private void OnRemove(T item)
        {
            //
            if (!events.IsNull())
            {
                events.RemoveEvent(new XBaseStorableDtoEventModel<T>(item));
            }
        }

        private void OnAddMany(IEnumerable<T> items)
        {
            //
            if (!events.IsNull())
            {
                events.AddManyEvent(new XBaseStorableDtoEventModel<IEnumerable<T>>(items));
            }
        }

        private void OnUpdateMany(IEnumerable<T> items)
        {
            //
            if (!events.IsNull())
            {
                events.UpdateManyEvent(new XBaseStorableDtoEventModel<IEnumerable<T>>(items));
            }
        }

        private void OnRemoveMany(IEnumerable<T> items)
        {
            //
            if (!events.IsNull())
            {
                events.RemoveManyEvent(new XBaseStorableDtoEventModel<IEnumerable<T>>(items));
            }
        }
        #endregion
        #endregion
    }
}
