This commit is contained in:
Wvader 2021-12-26 17:43:27 +00:00
parent 41accac4f7
commit f999e96b6f
10 changed files with 76 additions and 104 deletions

View File

@ -4,25 +4,32 @@ using System.Text;
namespace BlueWest.Data namespace BlueWest.Data
{ {
class DataQueryResult { } public sealed class DataQueryResult<T>
internal sealed class PositiveResult<T> : DataQueryResult
{ {
public readonly T Value; public readonly T Value;
public bool HasValue;
public string Message;
public PositiveResult(T value) public DataQueryResult(T value, bool success = true, string message = "")
{ {
Value = value; Value = value;
HasValue = success;
Message = message;
} }
} }
internal sealed class DataQueryResult
internal sealed class NegativeResult : DataQueryResult
{ {
public readonly string UserMessage; public readonly object Value;
public NegativeResult(string userMessage) public bool HasValue;
public string Message;
public DataQueryResult(object value, bool success = true, string message = "")
{ {
UserMessage = userMessage; Value = value;
HasValue = success;
Message = message;
} }
} }
} }

View File

@ -25,9 +25,9 @@ namespace BlueWest.Data
[Key(6)] public double BTCAmount { get; set; } [Key(6)] public double BTCAmount { get; set; }
[Key(7)] public double LTCAmount { get; set; } [Key(7)] public double LTCAmount { get; set; }
[Key(8)] public FastDictionary<FinanceTransaction> FinanceTransactions { get; set; } [Key(8)] public FastDictionary<int, FinanceTransaction> FinanceTransactions { get; }
public User(int id, string name, string address, string btcAddress, string ltcAddress, double btcAmount, double ltcAmount, FastList<FinanceTransaction> financeTransactions) public User(int id, string name, string address, string btcAddress, string ltcAddress, double btcAmount, double ltcAmount, FastDictionary<int, FinanceTransaction> financeTransactions)
{ {
Id = id; Id = id;
Name = name; Name = name;
@ -41,11 +41,11 @@ namespace BlueWest.Data
public void AddTransaction(FinanceTransaction financeTransaction) public void AddTransaction(FinanceTransaction financeTransaction)
{ {
FinanceTransactions.Add(financeTransaction); FinanceTransactions.Add(FinanceTransactions.Count + 1, financeTransaction);
} }
public void AddTransaction(FinanceTransactionInsertDto financeTransaction) public void AddTransaction(FinanceTransactionInsertDto financeTransaction)
{ {
FinanceTransactions.Add(new FinanceTransaction(financeTransaction)); FinanceTransactions.Add(FinanceTransactions.Count + 1, new FinanceTransaction(financeTransaction, FinanceTransactions.Count + 1));
} }
internal bool HasTransaction(int transactionId) internal bool HasTransaction(int transactionId)
@ -53,9 +53,9 @@ namespace BlueWest.Data
return FinanceTransactions.Contains(transactionId); return FinanceTransactions.Contains(transactionId);
} }
internal Transaction GetTransactionById(int transactionId) internal FinanceTransaction GetTransactionById(int transactionId)
{ {
return FinanceTransactions(transactionId); return FinanceTransactions[transactionId];
} }
} }
} }

View File

@ -11,7 +11,7 @@ namespace BlueWest.Data
{ {
[Key(9)] public readonly FastDictionary<int, User> Users; [Key(9)] public readonly FastDictionary<int, User> Users;
public int Length = 0; [IgnoreMember] public int Length = 0;
public UserList(FastDictionary<int, User> users) public UserList(FastDictionary<int, User> users)
{ {
@ -30,13 +30,13 @@ namespace BlueWest.Data
return -1; return -1;
} }
internal DataQueryResult GetUserById(int id) public DataQueryResult<User> GetUserById(int id)
{ {
if (Users.ContainsKey(id)) return new PositiveResult<User>(Users[id]); if (Users.ContainsKey(id)) return new DataQueryResult<User>(Users[id], true);
return new NegativeResult("Can't find a user with the provided id."); return new DataQueryResult<User>(null, false, "Can't find a user with the provided id.");
} }
internal bool RemoveUser(int userId) public bool RemoveUser(int userId)
{ {
if (Users.ContainsKey(userId)) if (Users.ContainsKey(userId))
{ {
@ -52,25 +52,30 @@ namespace BlueWest.Data
return Users.Contains(userId); return Users.Contains(userId);
} }
internal DataQueryResult UpdateUser(int userId, UserUpdateDto userUpdate) public DataQueryResult<User> UpdateUser(int userId, UserUpdateDto userUpdate)
{ {
Users[userId].Update(userUpdate); if (Users.ContainsKey(userId))
return Users[userId]; {
Users[userId].Update(userUpdate);
return new DataQueryResult<User>(Users[userId], true);
}
return new DataQueryResult<User>(null, false);
} }
internal bool UserHasTransaction(int userId, int transactionId) => HasUser(userId) && Users[userId].FinanceTransactions.Contains(transactionId); internal bool UserHasTransaction(int userId, int transactionId) => HasUser(userId) && Users[userId].FinanceTransactions.Contains(transactionId);
internal DataQueryResult GetTransactionById(int userId, int transactionId) public DataQueryResult<FinanceTransaction> GetTransactionById(int userId, int transactionId)
{ {
if(!HasUser(userId)) return new NegativeResult("Can't find a user with the provided id."); if(!HasUser(userId)) return new DataQueryResult<FinanceTransaction>(new FinanceTransaction(), false, "Can't find a user with the provided id.");
if (UserHasTransaction(userId, transactionId)) return new PositiveResult<Transaction>(Users[userId].FinanceTransactions[transactionId]); if (UserHasTransaction(userId, transactionId)) return new DataQueryResult<FinanceTransaction>(Users[userId].FinanceTransactions[transactionId]);
return new NegativeResult("No transaction was found with the specified id"); return new DataQueryResult<FinanceTransaction>(new FinanceTransaction(), false, "Can't find a transaction with the provided id.");
} }
internal User AddUser(int userId, UserUpdateDto userUpdateDto) public User AddUser(int userId, UserUpdateDto userUpdateDto)
{ {
if (Users.ContainsKey(userId)) if (Users.ContainsKey(userId))
{ {
@ -80,7 +85,7 @@ namespace BlueWest.Data
var id = userId != -1 ? userId : Length + 1; var id = userId != -1 ? userId : Length + 1;
var newUser = new User(userUpdateDto, id, new FastList<FinanceTransaction>()); var newUser = new User(userUpdateDto);
Users.Add(Length, newUser); Users.Add(Length, newUser);
@ -91,28 +96,28 @@ namespace BlueWest.Data
const string NoIdError = "No transaction was found with the specified id"; const string NoIdError = "No transaction was found with the specified id";
static NegativeResult NoIdResult = new NegativeResult(NoIdError); public DataQueryResult<FinanceTransaction> AddFinanceTransaction(int userId, FinanceTransactionInsertDto financeTransactionDto)
internal DataQueryResult AddFinanceTransaction(int userId, FinanceTransactionInsertDto financeTransactionDto)
{ {
if (Users.ContainsKey(userId)) if (Users.ContainsKey(userId))
{ {
var financeTransaction = new FinanceTransaction(financeTransactionDto); var financeTransaction = new FinanceTransaction(financeTransactionDto, Users[userId].FinanceTransactions.Count + 1);
Users[userId].AddTransaction(financeTransaction); Users[userId].AddTransaction(financeTransaction);
return new PositiveResult<BlueWest.Data.FinanceTransaction>(financeTransaction); return new DataQueryResult<FinanceTransaction>(financeTransaction);
} }
return NoIdResult; return new DataQueryResult<FinanceTransaction>(new FinanceTransaction(), false,
"no transaction with the provided id");
} }
internal FastList<FinanceTransaction> GetUserTransactions(int userId) public ImmutableArray<FinanceTransaction> GetUserTransactions(int userId)
{ {
if (Users.ContainsKey(userId)) if (Users.ContainsKey(userId))
{ {
return Users[userId].FinanceTransactions; return Users[userId].FinanceTransactions.Values.ToImmutableArray();
} }
return new FastList<FinanceTransaction>(); return new ImmutableArray<FinanceTransaction>();
} }
} }

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0-windows</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<LangVersion>10</LangVersion> <LangVersion>10</LangVersion>
</PropertyGroup> </PropertyGroup>

View File

@ -1,4 +1,5 @@
using BlueWest.Core.Tests; using System.Collections.Immutable;
using BlueWest.Collections;
using BlueWest.Data; using BlueWest.Data;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -18,7 +19,7 @@ namespace BlueWest.WebApi.Controllers
{ {
if (_userList != null) if (_userList != null)
{ {
return Ok(_userList); return Ok(_userList.Users.Values.ToImmutableArray());
} }
@ -31,9 +32,9 @@ namespace BlueWest.WebApi.Controllers
[HttpGet("{userId}", Name = nameof(GetUserById))] [HttpGet("{userId}", Name = nameof(GetUserById))]
public ActionResult GetUserById(int userId) public ActionResult GetUserById(int userId)
{ {
User? user = MemoryData.GetUserById(userId); DataQueryResult<User> user = MemoryData.GetUserById(userId);
if (user != null) if (user.HasValue)
{ {
return Ok(user.Value); return Ok(user.Value);
@ -49,7 +50,7 @@ namespace BlueWest.WebApi.Controllers
public ActionResult GetTransactions(int userId) public ActionResult GetTransactions(int userId)
{ {
var transactions = MemoryData.GetUserTransactions(userId); var transactions = MemoryData.GetUserTransactions(userId);
return OK(transactions.ToDictionary()); return Ok(transactions);
} }
@ -60,9 +61,11 @@ namespace BlueWest.WebApi.Controllers
{ {
var user = MemoryData.UserList.GetUserById(userId); var user = MemoryData.UserList.GetUserById(userId);
var transactions = user?.FinanceTransactions; if(!user.HasValue) return new NotFoundResult();
FinanceTransaction? transaction = transactions?.FirstOrNull(t => t.Id == transactionId); var transactions = user?.Value.FinanceTransactions;
FinanceTransaction? transaction = transactions?.Values.ToImmutableArray().FirstOrNull(t => t.Id == transactionId);
if (transaction != null) if (transaction != null)
{ {
@ -113,9 +116,9 @@ namespace BlueWest.WebApi.Controllers
[HttpPost("{userId}/transactions")] [HttpPost("{userId}/transactions")]
public ActionResult PostTransaction(int userId, FinanceTransactionInsertDto financeTransaction) public ActionResult PostTransaction(int userId, FinanceTransactionInsertDto financeTransaction)
{ {
FinanceTransaction? result = MemoryData.UserList.AddFinanceTransaction(userId, financeTransaction); DataQueryResult<FinanceTransaction> result = MemoryData.UserList.AddFinanceTransaction(userId, financeTransaction);
if(result != null) return Ok(result); if(result.HasValue) return Ok(result.Value);
return new BadRequestResult(); return new BadRequestResult();
} }

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>disable</ImplicitUsings> <ImplicitUsings>disable</ImplicitUsings>
<RootNamespace>PerformanceSolution</RootNamespace> <RootNamespace>PerformanceSolution</RootNamespace>

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Dynamic; using System.Dynamic;
using System.Linq; using System.Linq;
using BlueWest.Core.Tests;
using BlueWest.DataAgent; using BlueWest.DataAgent;
namespace BlueWest.Core namespace BlueWest.Core

View File

@ -1,44 +1 @@
using System; 
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace BlueWest.Core.Tests
{
public static class PocoToDictionary
{
private static readonly MethodInfo AddToDicitonaryMethod = typeof(IDictionary<string, object>).GetMethod("Add");
private static readonly ConcurrentDictionary<Type, Func<object, IDictionary<string, object>>> Converters = new ConcurrentDictionary<Type, Func<object, IDictionary<string, object>>>();
private static readonly ConstructorInfo DictionaryConstructor = typeof(Dictionary<string, object>).GetConstructors().FirstOrDefault(c => c.IsPublic && !c.GetParameters().Any());
public static IDictionary<int, object> ToDictionary(this object obj) => obj == null ? null : Converters.GetOrAdd(obj.GetType(), o =>
{
var outputType = typeof(IDictionary<int, object>);
var inputType = obj.GetType();
var inputExpression = Expression.Parameter(typeof(object), "input");
var typedInputExpression = Expression.Convert(inputExpression, inputType);
var outputVariable = Expression.Variable(outputType, "output");
var returnTarget = Expression.Label(outputType);
var body = new List<Expression>
{
Expression.Assign(outputVariable, Expression.New(DictionaryConstructor))
};
body.AddRange(
from prop in inputType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy)
where prop.CanRead && (prop.PropertyType.IsPrimitive || prop.PropertyType == typeof(int))
let getExpression = Expression.Property(typedInputExpression, prop.GetMethod)
let convertExpression = Expression.Convert(getExpression, typeof(object))
select Expression.Call(outputVariable, AddToDicitonaryMethod, Expression.Constant(prop.Name), convertExpression));
body.Add(Expression.Return(returnTarget, outputVariable));
body.Add(Expression.Label(returnTarget, Expression.Constant(null, outputType)));
var lambdaExpression = Expression.Lambda<Func<object, IDictionary<int, object>>>(
Expression.Block(new[] { outputVariable }, body),
inputExpression);
return lambdaExpression.Compile();
})(obj);
}
}

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Transactions; using System.Transactions;
using BlueWest.Collections; using BlueWest.Collections;
using BlueWest.Data; using BlueWest.Data;
@ -20,16 +21,16 @@ namespace PerformanceSolution.Data
if (DEBUG) if (DEBUG)
{ {
UserList = GenerateMockData(); UserList = GenerateMockData();
SaveUserList(); //SaveUserList();
} }
LoadUsers(); //LoadUsers();
} }
public static void SaveUserList(UserList userList) public static void SaveUserList(UserList userList)
{ {
UserList = userList; //UserList = userList;
SaveLoadManager.Save(UserList, SavePathName); //SaveLoadManager.Save(UserList, SavePathName);
} }
public static void LoadUsers() public static void LoadUsers()
@ -38,7 +39,7 @@ namespace PerformanceSolution.Data
UserList ??= new UserList(new FastDictionary<int, User>()); UserList ??= new UserList(new FastDictionary<int, User>());
} }
public static Transaction GetTransactionById(int userId, int transactionId) => UserList.GetTransactionById(userId, transactionId); public static DataQueryResult<FinanceTransaction> GetTransactionById(int userId, int transactionId) => UserList.GetTransactionById(userId, transactionId);
private static void SaveUserList() => SaveUserList(UserList); private static void SaveUserList() => SaveUserList(UserList);
@ -53,10 +54,10 @@ namespace PerformanceSolution.Data
{ {
var transactions = new FastList<FinanceTransaction>(); var transactions = new FastDictionary<int, FinanceTransaction>();
var financeTransaction = new FinanceTransaction(0, 1, FinanceTransactionType.Buy, FinanceSymbol.BTC_EUR, 0, var financeTransaction = new FinanceTransaction(0, 1, FinanceTransactionType.Buy, FinanceSymbol.BTC_EUR, 0,
0, 0.1, DateTime.Now); 0, 0.1, DateTime.Now);
transactions.Add(financeTransaction); transactions.Add(1, financeTransaction);
var u = new User(1, "Rui Sousa", "Sagres", "NOADD", "NOADD", 0, 0, transactions); var u = new User(1, "Rui Sousa", "Sagres", "NOADD", "NOADD", 0, 0, transactions);
var list = new FastDictionary<int, User>(10); var list = new FastDictionary<int, User>(10);
@ -65,12 +66,12 @@ namespace PerformanceSolution.Data
return new UserList(list); return new UserList(list);
} }
public static User? GetUserById(int userId) public static DataQueryResult<User> GetUserById(int userId)
{ {
return UserList.GetUserById(userId); return UserList.GetUserById(userId);
} }
public static FastList<FinanceTransaction> GetUserTransactions(int userId) public static ImmutableArray<FinanceTransaction> GetUserTransactions(int userId)
{ {
return UserList.GetUserTransactions(userId); return UserList.GetUserTransactions(userId);
} }

2
MapTo

@ -1 +1 @@
Subproject commit 9470afb737d873f2fbbc631813eadf10032c5c6b Subproject commit ffc3dc7729c97190849441d73edb2dfc5fe63ecd