From b0c6a679e8f20d5f55b0f0ed82dc782fa956bfc0 Mon Sep 17 00:00:00 2001 From: Jonny Olliff-Lee Date: Fri, 27 Mar 2020 20:11:01 +0000 Subject: [PATCH 1/2] Adds QueryProcessor and intitial query --- KillTeam/Controllers/TeamsController.cs | 22 ++++++------ KillTeam/Models/Team.cs | 4 +-- KillTeam/Queries/AllTeamsQuery.cs | 7 ++++ .../Queries/Handlers/AllTeamsQueryHandler.cs | 26 ++++++++++++++ KillTeam/Queries/Handlers/IQueryHandler.cs | 9 +++++ KillTeam/Queries/Handlers/IQueryProcessor.cs | 35 +++++++++++++++++++ KillTeam/Queries/IQuery.cs | 7 ++++ KillTeam/Views/TeamsView.xaml.cs | 7 +++- 8 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 KillTeam/Queries/AllTeamsQuery.cs create mode 100644 KillTeam/Queries/Handlers/AllTeamsQueryHandler.cs create mode 100644 KillTeam/Queries/Handlers/IQueryHandler.cs create mode 100644 KillTeam/Queries/Handlers/IQueryProcessor.cs create mode 100644 KillTeam/Queries/IQuery.cs diff --git a/KillTeam/Controllers/TeamsController.cs b/KillTeam/Controllers/TeamsController.cs index 897ad6a..29faa4e 100644 --- a/KillTeam/Controllers/TeamsController.cs +++ b/KillTeam/Controllers/TeamsController.cs @@ -5,7 +5,8 @@ using System.Windows.Input; using KillTeam.Commands; using KillTeam.Commands.Handlers; - +using KillTeam.Queries; +using KillTeam.Queries.Handlers; using KillTeam.Services; using KillTeam.ViewModels; using Microsoft.EntityFrameworkCore; @@ -23,9 +24,11 @@ public class TeamsController public ICommand OpenTeam { get; private set; } public ICommand DeleteTeam { get; private set; } - public TeamsController(IList toolbarItems, + public TeamsController( + IList toolbarItems, IHandleCommands deleteTeamCommandHandler, - IHandleCommands reorderTeamsCommandHandler) + IHandleCommands reorderTeamsCommandHandler, + IQueryProcessor queryProcessor) { Items = new ObservableCollection(); @@ -34,6 +37,7 @@ public TeamsController(IList toolbarItems, _reorderTeamsCommandHandler = reorderTeamsCommandHandler; _deleteTeamCommandHandler = deleteTeamCommandHandler; + _queryProcessor = queryProcessor; } public async Task Refresh() @@ -76,13 +80,10 @@ private void InitializeCommands() private async Task UpdateItems() { Items.Clear(); - var teams = await KTContext.Db.Teams - .Include(e => e.Faction) - .Include(e => e.Members) - .AsNoTracking() - .OrderBy(post => post.Position) - .ToListAsync(); - teams.ForEach(i => Items.Add(new TeamsViewModel(i.Id, i.Name, i.Cost, i.FactionNameAndMembersCount))); + + var teams = await _queryProcessor.Execute>(new AllTeamsQuery()); + + teams.ForEach(t => Items.Add(t)); } private void AddTeamExecuted() @@ -124,5 +125,6 @@ private async Task VersionExecuted() private readonly IHandleCommands _reorderTeamsCommandHandler; private readonly IHandleCommands _deleteTeamCommandHandler; + private readonly IQueryProcessor _queryProcessor; } } diff --git a/KillTeam/Models/Team.cs b/KillTeam/Models/Team.cs index 25081e8..019d7ea 100644 --- a/KillTeam/Models/Team.cs +++ b/KillTeam/Models/Team.cs @@ -185,8 +185,8 @@ public string FactionNameAndMembersCount { get { - int count = GetSelectedMembers().Count(); - return Faction.Name + " - " + count + " " + (count <= 1 ? Properties.Resources.Membre : Properties.Resources.Membres); + var count = GetSelectedMembers().Count(); + return $"{Faction.Name} - {count} {(count <= 1 ? Properties.Resources.Membre : Properties.Resources.Membres)}"; } } diff --git a/KillTeam/Queries/AllTeamsQuery.cs b/KillTeam/Queries/AllTeamsQuery.cs new file mode 100644 index 0000000..f60064f --- /dev/null +++ b/KillTeam/Queries/AllTeamsQuery.cs @@ -0,0 +1,7 @@ +namespace KillTeam.Queries +{ + public class AllTeamsQuery : IQuery + { + + } +} \ No newline at end of file diff --git a/KillTeam/Queries/Handlers/AllTeamsQueryHandler.cs b/KillTeam/Queries/Handlers/AllTeamsQueryHandler.cs new file mode 100644 index 0000000..30114c5 --- /dev/null +++ b/KillTeam/Queries/Handlers/AllTeamsQueryHandler.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using KillTeam.Services; +using KillTeam.ViewModels; +using Microsoft.EntityFrameworkCore; + +namespace KillTeam.Queries.Handlers +{ + public class AllTeamsQueryHandler : IQueryHandler> + { + public async Task> Execute(AllTeamsQuery query) + { + var teams = await KTContext.Db.Teams + .Include(e => e.Faction) + .Include(e => e.Members) + .AsNoTracking() + .OrderBy(post => post.Position) + .ToListAsync(); + + return teams + .Select(t => new TeamsViewModel(t.Id, t.Name, t.Cost, t.FactionNameAndMembersCount)) + .ToList(); + } + } +} \ No newline at end of file diff --git a/KillTeam/Queries/Handlers/IQueryHandler.cs b/KillTeam/Queries/Handlers/IQueryHandler.cs new file mode 100644 index 0000000..9b777f0 --- /dev/null +++ b/KillTeam/Queries/Handlers/IQueryHandler.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace KillTeam.Queries.Handlers +{ + public interface IQueryHandler where TQuery : IQuery + { + Task Execute(TQuery query); + } +} \ No newline at end of file diff --git a/KillTeam/Queries/Handlers/IQueryProcessor.cs b/KillTeam/Queries/Handlers/IQueryProcessor.cs new file mode 100644 index 0000000..5b53af6 --- /dev/null +++ b/KillTeam/Queries/Handlers/IQueryProcessor.cs @@ -0,0 +1,35 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; + +namespace KillTeam.Queries.Handlers +{ + public interface IQueryProcessor + { + Task Execute(TQuery query) where TQuery : IQuery; + } + + public class QueryProcessor : IQueryProcessor + { + public static IQueryProcessor Instance() => _queryProcessor; + + private static readonly IQueryProcessor _queryProcessor = new QueryProcessor(); + + public async Task Execute(TQuery query) where TQuery : IQuery + { + var handlerType = + Assembly + .GetAssembly(typeof(TQuery)) + .DefinedTypes + .FirstOrDefault(t => t.ImplementedInterfaces.Contains(typeof(IQueryHandler))); + + if (handlerType is null) + throw new InvalidOperationException($"No query handler for Query {typeof(TQuery)} for result {typeof(TResult)}"); + + var handler = Activator.CreateInstance(handlerType) as IQueryHandler; + + return await handler.Execute(query); + } + } +} \ No newline at end of file diff --git a/KillTeam/Queries/IQuery.cs b/KillTeam/Queries/IQuery.cs new file mode 100644 index 0000000..dae158c --- /dev/null +++ b/KillTeam/Queries/IQuery.cs @@ -0,0 +1,7 @@ +namespace KillTeam.Queries +{ + public interface IQuery + { + + } +} \ No newline at end of file diff --git a/KillTeam/Views/TeamsView.xaml.cs b/KillTeam/Views/TeamsView.xaml.cs index a3e29c5..1d4367a 100644 --- a/KillTeam/Views/TeamsView.xaml.cs +++ b/KillTeam/Views/TeamsView.xaml.cs @@ -1,5 +1,6 @@ using KillTeam.Commands.Handlers; using KillTeam.Controllers; +using KillTeam.Queries.Handlers; using Xamarin.Forms.PlatformConfiguration.iOSSpecific; using Xamarin.Forms.Xaml; @@ -13,7 +14,11 @@ public TeamsView() InitializeComponent(); On().SetUseSafeArea(true); - BindingContext = new TeamsController(ToolbarItems, new DeleteTeamCommandHandler(), new ReorderTeamsCommandHandler()); + BindingContext = new TeamsController( + ToolbarItems, + new DeleteTeamCommandHandler(), + new ReorderTeamsCommandHandler(), + QueryProcessor.Instance()); } protected override async void OnAppearing() From 2590aa4b65aeb90f0641a9e9f7b91c28b2ae5bcb Mon Sep 17 00:00:00 2001 From: Jonny Olliff-Lee Date: Sat, 28 Mar 2020 17:40:50 +0000 Subject: [PATCH 2/2] Moves Team subtitle calculation to AllTeamsQueryHandler --- KillTeam/Models/Team.cs | 10 ---------- .../Queries/Handlers/AllTeamsQueryHandler.cs | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/KillTeam/Models/Team.cs b/KillTeam/Models/Team.cs index 019d7ea..e98a169 100644 --- a/KillTeam/Models/Team.cs +++ b/KillTeam/Models/Team.cs @@ -179,16 +179,6 @@ public List Errors return liste; } } - - [JsonIgnore] - public string FactionNameAndMembersCount - { - get - { - var count = GetSelectedMembers().Count(); - return $"{Faction.Name} - {count} {(count <= 1 ? Properties.Resources.Membre : Properties.Resources.Membres)}"; - } - } #endregion Calculated Properties diff --git a/KillTeam/Queries/Handlers/AllTeamsQueryHandler.cs b/KillTeam/Queries/Handlers/AllTeamsQueryHandler.cs index 30114c5..2fad92b 100644 --- a/KillTeam/Queries/Handlers/AllTeamsQueryHandler.cs +++ b/KillTeam/Queries/Handlers/AllTeamsQueryHandler.cs @@ -16,10 +16,26 @@ public async Task> Execute(AllTeamsQuery query) .Include(e => e.Members) .AsNoTracking() .OrderBy(post => post.Position) + .Select(t => new + { + t.Id, + t.Name, + t.Members, + t.Faction, + t.Roster + }) .ToListAsync(); return teams - .Select(t => new TeamsViewModel(t.Id, t.Name, t.Cost, t.FactionNameAndMembersCount)) + .Select(t => + { + var selectedMembers = t.Members.Where(m => m.Selected || !t.Roster).ToList(); + var count = selectedMembers.Count(); + var cost = selectedMembers.Sum(m => m.Cost); + var subtitle = $"{t.Faction.Name} - {count} {(count <= 1 ? Properties.Resources.Membre : Properties.Resources.Membres)}"; + + return new TeamsViewModel(t.Id, t.Name, cost, subtitle); + }) .ToList(); } }