Initial Commit ...
This commit is contained in:
@@ -0,0 +1,521 @@
|
||||
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> ();
|
||||
|
||||
//
|
||||
#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);
|
||||
|
||||
//
|
||||
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));
|
||||
|
||||
//
|
||||
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);
|
||||
|
||||
//
|
||||
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 {
|
||||
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 })
|
||||
);
|
||||
}
|
||||
|
||||
private void RemoveItemsFromStore (IEnumerable<T> items) {
|
||||
STORE = new ConcurrentBag<T> (
|
||||
STORE.Except (items)
|
||||
);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user