mirror of https://github.com/Squidex/squidex.git
62 changed files with 1402 additions and 364 deletions
@ -0,0 +1,26 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
|
|||
namespace PinkParrot.Modules.Api.Schemas |
|||
{ |
|||
public class SchemasController : Controller |
|||
{ |
|||
[HttpPost] |
|||
[Route("schemas/")] |
|||
public async Task Create() |
|||
{ |
|||
} |
|||
|
|||
[HttpPut] |
|||
[Route("schemas/{name}/")] |
|||
public async Task Update() |
|||
{ |
|||
} |
|||
|
|||
[HttpDelete] |
|||
[Route("schemas/{name}/")] |
|||
public async Task Delete() |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,187 +0,0 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="utf-8" /> |
|||
<title>Welcome to ASP.NET Core</title> |
|||
<style> |
|||
html { |
|||
background: #f1f1f1; |
|||
height: 100%; |
|||
} |
|||
|
|||
body { |
|||
background: #fff; |
|||
color: #505050; |
|||
font: 14px 'Segoe UI', tahoma, arial, helvetica, sans-serif; |
|||
margin: 1%; |
|||
min-height: 95.5%; |
|||
border: 1px solid silver; |
|||
position: relative; |
|||
} |
|||
|
|||
#header { |
|||
padding: 0; |
|||
} |
|||
|
|||
#header h1 { |
|||
font-size: 44px; |
|||
font-weight: normal; |
|||
margin: 0; |
|||
padding: 10px 30px 10px 30px; |
|||
} |
|||
|
|||
#header span { |
|||
margin: 0; |
|||
padding: 0 30px; |
|||
display: block; |
|||
} |
|||
|
|||
#header p { |
|||
font-size: 20px; |
|||
color: #fff; |
|||
background: #007acc; |
|||
padding: 0 30px; |
|||
line-height: 50px; |
|||
margin-top: 25px; |
|||
|
|||
} |
|||
|
|||
#header p a { |
|||
color: #fff; |
|||
text-decoration: underline; |
|||
font-weight: bold; |
|||
padding-right: 35px; |
|||
background: no-repeat right bottom url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAWCAMAAAAcqPc3AAAANlBMVEUAAAAAeswfitI9mthXp91us+KCvuaTx+mjz+2x1u+83PLH4vTR5/ba7Pjj8Pns9fv1+v3////wy3dWAAAAAXRSTlMAQObYZgAAAHxJREFUeNp9kVcSwCAIRMHUYoH7XzaxOxJ9P8oyQ1uIqNPwh3s2aLmIM2YtqrLcQIeQEylhuCeUOlhgve5yoBCfWmlnlgkN4H8ykbpaE7gR03AbUHiwoOxUH9Xp+ubd41p1HF3mBPrfC87BHeTdaB3ceeKL9HGpcvX9zu6+DdMWT9KQPvYAAAAASUVORK5CYII=); |
|||
} |
|||
|
|||
#main { |
|||
padding: 5px 30px; |
|||
clear: both; |
|||
} |
|||
|
|||
.section { |
|||
width: 21.7%; |
|||
float: left; |
|||
margin: 0 0 0 4%; |
|||
} |
|||
|
|||
.section h2 { |
|||
font-size: 13px; |
|||
text-transform: uppercase; |
|||
margin: 0; |
|||
border-bottom: 1px solid silver; |
|||
padding-bottom: 12px; |
|||
margin-bottom: 8px; |
|||
} |
|||
|
|||
.section.first { |
|||
margin-left: 0; |
|||
} |
|||
|
|||
.section.first h2 { |
|||
font-size: 24px; |
|||
text-transform: none; |
|||
margin-bottom: 25px; |
|||
border: none; |
|||
} |
|||
|
|||
.section.first li { |
|||
border-top: 1px solid silver; |
|||
padding: 8px 0; |
|||
} |
|||
|
|||
.section.last { |
|||
margin-right: 0; |
|||
} |
|||
|
|||
ul { |
|||
list-style: none; |
|||
padding: 0; |
|||
margin: 0; |
|||
line-height: 20px; |
|||
} |
|||
|
|||
li { |
|||
padding: 4px 0; |
|||
} |
|||
|
|||
a { |
|||
color: #267cb2; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
a:hover { |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
#footer { |
|||
clear: both; |
|||
padding-top: 50px; |
|||
} |
|||
|
|||
#footer p { |
|||
position: absolute; |
|||
bottom: 10px; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
|
|||
<div id="header"> |
|||
<h1>Welcome to ASP.NET Core</h1> |
|||
<span> |
|||
We've made some big updates in this release, so it’s <b>important</b> that you spend |
|||
a few minutes to learn what’s new. |
|||
</span> |
|||
<p>You've created a new ASP.NET Core project. <a href="http://go.microsoft.com/fwlink/?LinkId=518016">Learn what's new</a></p> |
|||
</div> |
|||
|
|||
<div id="main"> |
|||
<div class="section first"> |
|||
<h2>This application consists of:</h2> |
|||
<ul> |
|||
<li>Sample pages using ASP.NET Core MVC</li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518004">Bower</a> for managing client-side libraries</li> |
|||
<li>Theming using <a href="http://go.microsoft.com/fwlink/?LinkID=398939">Bootstrap</a></li> |
|||
</ul> |
|||
</div> |
|||
<div class="section"> |
|||
<h2>How to</h2> |
|||
<ul> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398600">Add a Controller and View</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699562">Add an appsetting in config and access it in app.</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699315">Manage User Secrets using Secret Manager.</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699316">Use logging to log a message.</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699317">Add packages using NuGet.</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699318">Add client packages using Bower.</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699319">Target development, staging or production environment.</a></li> |
|||
</ul> |
|||
</div> |
|||
<div class="section"> |
|||
<h2>Overview</h2> |
|||
<ul> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518008">Conceptual overview of what is ASP.NET Core</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=699320">Fundamentals of ASP.NET Core such as Startup and middleware.</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=398602">Working with Data</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=398603">Security</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699321">Client side development</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699322">Develop on different platforms</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=699323">Read more on the documentation site</a></li> |
|||
</ul> |
|||
</div> |
|||
<div class="section last"> |
|||
<h2>Run & Deploy</h2> |
|||
<ul> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517851">Run your app</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517853">Run tools such as EF migrations and more</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398609">Publish to Microsoft Azure Web Apps</a></li> |
|||
</ul> |
|||
</div> |
|||
|
|||
<div id="footer"> |
|||
<p>We would love to hear your <a href="http://go.microsoft.com/fwlink/?LinkId=518015">feedback</a></p> |
|||
</div> |
|||
</div> |
|||
|
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,284 @@ |
|||
// ==========================================================================
|
|||
// DispatchingTests.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
using PinkParrot.Infrastructure.Dispatching; |
|||
using PinkParrot.Infrastructure.Tasks; |
|||
using Xunit; |
|||
|
|||
namespace PinkParrot.Infrastructure |
|||
{ |
|||
public sealed class DispatchingTests |
|||
{ |
|||
private interface IEvent { } |
|||
|
|||
private class EventA : IEvent { } |
|||
private class EventB : IEvent { } |
|||
private class Unknown : IEvent { } |
|||
|
|||
private class AsyncFuncConsumer |
|||
{ |
|||
public int EventATriggered { get; private set; } |
|||
public int EventBTriggered { get; private set; } |
|||
|
|||
public Task<int> DispatchEventAsync(IEvent @event) |
|||
{ |
|||
return this.DispatchFuncAsync(@event, 9); |
|||
} |
|||
|
|||
public Task<int> DispatchEventAsync(IEvent @event, int context) |
|||
{ |
|||
return this.DispatchFuncAsync(@event, context, 13); |
|||
} |
|||
|
|||
public Task<int> On(EventA @event) |
|||
{ |
|||
return Task.FromResult(++EventATriggered); |
|||
} |
|||
|
|||
public Task<int> On(EventB @event) |
|||
{ |
|||
return Task.FromResult(++EventBTriggered); |
|||
} |
|||
|
|||
public Task<int> On(EventA @event, int context) |
|||
{ |
|||
return Task.FromResult(++EventATriggered + context); |
|||
} |
|||
|
|||
public Task<int> On(EventB @event, int context) |
|||
{ |
|||
return Task.FromResult(++EventBTriggered + context); |
|||
} |
|||
} |
|||
|
|||
private class AsyncConsumer |
|||
{ |
|||
public int EventATriggered { get; private set; } |
|||
public int EventBTriggered { get; private set; } |
|||
|
|||
public Task<bool> DispatchEventAsync(IEvent @event) |
|||
{ |
|||
return this.DispatchActionAsync(@event); |
|||
} |
|||
|
|||
public Task<bool> DispatchEventAsync(IEvent @event, int context) |
|||
{ |
|||
return this.DispatchActionAsync(@event, context); |
|||
} |
|||
|
|||
public Task On(EventA @event) |
|||
{ |
|||
EventATriggered++; |
|||
return TaskHelper.Done; |
|||
} |
|||
|
|||
public Task On(EventB @event) |
|||
{ |
|||
EventBTriggered++; |
|||
return TaskHelper.Done; |
|||
} |
|||
|
|||
public Task On(EventA @event, int context) |
|||
{ |
|||
EventATriggered = EventATriggered + context; |
|||
return TaskHelper.Done; |
|||
} |
|||
|
|||
public Task On(EventB @event, int context) |
|||
{ |
|||
EventBTriggered = EventATriggered + context; |
|||
return TaskHelper.Done; |
|||
} |
|||
} |
|||
|
|||
private class SyncFuncConsumer |
|||
{ |
|||
public int EventATriggered { get; private set; } |
|||
public int EventBTriggered { get; private set; } |
|||
|
|||
public int DispatchEvent(IEvent @event) |
|||
{ |
|||
return this.DispatchFunc(@event, 9); |
|||
} |
|||
|
|||
public int DispatchEvent(IEvent @event, int context) |
|||
{ |
|||
return this.DispatchFunc(@event, context, 13); |
|||
} |
|||
|
|||
public int On(EventA @event) |
|||
{ |
|||
return ++EventATriggered; |
|||
} |
|||
|
|||
public int On(EventB @event) |
|||
{ |
|||
return ++EventBTriggered; |
|||
} |
|||
|
|||
public int On(EventA @event, int context) |
|||
{ |
|||
return ++EventATriggered + context; |
|||
} |
|||
|
|||
public int On(EventB @event, int context) |
|||
{ |
|||
return ++EventBTriggered + context; |
|||
} |
|||
} |
|||
|
|||
private class SyncActionConsumer |
|||
{ |
|||
public int EventATriggered { get; private set; } |
|||
public int EventBTriggered { get; private set; } |
|||
|
|||
public bool DispatchEvent(IEvent @event) |
|||
{ |
|||
return this.DispatchAction(@event); |
|||
} |
|||
|
|||
public bool DispatchEvent(IEvent @event, int context) |
|||
{ |
|||
return this.DispatchAction(@event, context); |
|||
} |
|||
|
|||
public void On(EventA @event) |
|||
{ |
|||
EventATriggered++; |
|||
} |
|||
|
|||
public void On(EventB @event) |
|||
{ |
|||
EventBTriggered++; |
|||
} |
|||
|
|||
public void On(EventA @event, int context) |
|||
{ |
|||
EventATriggered = EventATriggered + context; |
|||
} |
|||
|
|||
public void On(EventB @event, int context) |
|||
{ |
|||
EventBTriggered = EventATriggered + context; |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_invoke_correct_event() |
|||
{ |
|||
var consumer = new SyncActionConsumer(); |
|||
|
|||
consumer.DispatchEvent(new EventA()); |
|||
consumer.DispatchEvent(new EventB()); |
|||
consumer.DispatchEvent(new EventB()); |
|||
consumer.DispatchEvent(new Unknown()); |
|||
|
|||
Assert.Equal(1, consumer.EventATriggered); |
|||
Assert.Equal(2, consumer.EventBTriggered); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_invoke_correct_event_with_context() |
|||
{ |
|||
var consumer = new SyncActionConsumer(); |
|||
|
|||
consumer.DispatchEvent(new EventA(), 2); |
|||
consumer.DispatchEvent(new EventB(), 2); |
|||
consumer.DispatchEvent(new EventB(), 2); |
|||
consumer.DispatchEvent(new Unknown(), 2); |
|||
|
|||
Assert.Equal(2, consumer.EventATriggered); |
|||
Assert.Equal(4, consumer.EventBTriggered); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_invoke_correct_event_asynchronously() |
|||
{ |
|||
var consumer = new AsyncConsumer(); |
|||
|
|||
await consumer.DispatchEventAsync(new EventA()); |
|||
await consumer.DispatchEventAsync(new EventB()); |
|||
await consumer.DispatchEventAsync(new EventB()); |
|||
await consumer.DispatchEventAsync(new Unknown()); |
|||
|
|||
Assert.Equal(1, consumer.EventATriggered); |
|||
Assert.Equal(2, consumer.EventBTriggered); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_invoke_correct_event_with_context_asynchronously() |
|||
{ |
|||
var consumer = new AsyncConsumer(); |
|||
|
|||
await consumer.DispatchEventAsync(new EventA(), 2); |
|||
await consumer.DispatchEventAsync(new EventB(), 2); |
|||
await consumer.DispatchEventAsync(new EventB(), 2); |
|||
await consumer.DispatchEventAsync(new Unknown(), 2); |
|||
|
|||
Assert.Equal(2, consumer.EventATriggered); |
|||
Assert.Equal(4, consumer.EventBTriggered); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_invoke_correct_event_and_return() |
|||
{ |
|||
var consumer = new SyncFuncConsumer(); |
|||
|
|||
Assert.Equal(1, consumer.DispatchEvent(new EventA())); |
|||
Assert.Equal(1, consumer.DispatchEvent(new EventB())); |
|||
Assert.Equal(2, consumer.DispatchEvent(new EventB())); |
|||
Assert.Equal(9, consumer.DispatchEvent(new Unknown())); |
|||
|
|||
Assert.Equal(1, consumer.EventATriggered); |
|||
Assert.Equal(2, consumer.EventBTriggered); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_invoke_correct_event_with_context_and_return() |
|||
{ |
|||
var consumer = new SyncFuncConsumer(); |
|||
|
|||
Assert.Equal(11, consumer.DispatchEvent(new EventA(), 10)); |
|||
Assert.Equal(11, consumer.DispatchEvent(new EventB(), 10)); |
|||
Assert.Equal(12, consumer.DispatchEvent(new EventB(), 10)); |
|||
Assert.Equal(13, consumer.DispatchEvent(new Unknown(), 10)); |
|||
|
|||
Assert.Equal(1, consumer.EventATriggered); |
|||
Assert.Equal(2, consumer.EventBTriggered); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_invoke_correct_event_and_return_synchronously() |
|||
{ |
|||
var consumer = new AsyncFuncConsumer(); |
|||
|
|||
Assert.Equal(1, await consumer.DispatchEventAsync(new EventA())); |
|||
Assert.Equal(1, await consumer.DispatchEventAsync(new EventB())); |
|||
Assert.Equal(2, await consumer.DispatchEventAsync(new EventB())); |
|||
Assert.Equal(9, await consumer.DispatchEventAsync(new Unknown())); |
|||
|
|||
Assert.Equal(1, consumer.EventATriggered); |
|||
Assert.Equal(2, consumer.EventBTriggered); |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_invoke_correct_event_with_context_and_return_synchronously() |
|||
{ |
|||
var consumer = new AsyncFuncConsumer(); |
|||
|
|||
Assert.Equal(11, await consumer.DispatchEventAsync(new EventA(), 10)); |
|||
Assert.Equal(11, await consumer.DispatchEventAsync(new EventB(), 10)); |
|||
Assert.Equal(12, await consumer.DispatchEventAsync(new EventB(), 10)); |
|||
Assert.Equal(13, await consumer.DispatchEventAsync(new Unknown(), 10)); |
|||
|
|||
Assert.Equal(1, consumer.EventATriggered); |
|||
Assert.Equal(2, consumer.EventBTriggered); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
// ==========================================================================
|
|||
// AggregateCommand.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS.Commands |
|||
{ |
|||
public class AggregateCommand : ICommand |
|||
{ |
|||
public Guid AggregateId { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
// ==========================================================================
|
|||
// CommandContext.cs
|
|||
// Green Parrot Framework
|
|||
// ==========================================================================
|
|||
// Copyright (c) Sebastian Stehle
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS.Commands |
|||
{ |
|||
public sealed class CommandContext |
|||
{ |
|||
private readonly IDomainObjectFactory factory; |
|||
private readonly IDomainObjectRepository repository; |
|||
private readonly ICommand command; |
|||
private Exception exception; |
|||
private bool isSucceeded; |
|||
|
|||
public ICommand Command |
|||
{ |
|||
get { return command; } |
|||
} |
|||
|
|||
public IDomainObjectFactory Factory |
|||
{ |
|||
get { return factory; } |
|||
} |
|||
|
|||
public IDomainObjectRepository Repository |
|||
{ |
|||
get { return repository; } |
|||
} |
|||
|
|||
public bool IsHandled |
|||
{ |
|||
get { return isSucceeded || exception != null; } |
|||
} |
|||
|
|||
public bool IsSucceeded |
|||
{ |
|||
get { return isSucceeded; } |
|||
} |
|||
|
|||
public Exception Exception |
|||
{ |
|||
get { return exception; } |
|||
} |
|||
|
|||
public CommandContext(IDomainObjectFactory factory, IDomainObjectRepository repository, ICommand command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
Guard.NotNull(factory, nameof(factory)); |
|||
Guard.NotNull(repository, nameof(repository)); |
|||
|
|||
this.command = command; |
|||
this.factory = factory; |
|||
this.repository = repository; |
|||
} |
|||
|
|||
public void MarkSucceeded() |
|||
{ |
|||
isSucceeded = true; |
|||
} |
|||
|
|||
public void MarkFailed(Exception handlerException) |
|||
{ |
|||
exception = handlerException; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
// ==========================================================================
|
|||
// CommandingExtensions.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS.Commands |
|||
{ |
|||
public static class CommandingExtensions |
|||
{ |
|||
public static T CreateNew<T>(this IDomainObjectFactory factory, Guid id) where T : DomainObject |
|||
{ |
|||
return (T)factory.CreateNew(typeof(T), id); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
// ==========================================================================
|
|||
// ICommand.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS.Commands |
|||
{ |
|||
public interface ICommand |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
// ==========================================================================
|
|||
// ICommandBus.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS.Commands |
|||
{ |
|||
public interface ICommandBus |
|||
{ |
|||
Task PublishAsync(ICommand command); |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
// ==========================================================================
|
|||
// ICommandHandler.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS.Commands |
|||
{ |
|||
public interface ICommandHandler |
|||
{ |
|||
Task<bool> HandleAsync(CommandContext context); |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
// ==========================================================================
|
|||
// IDomainObjectFactory.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS.Commands |
|||
{ |
|||
public interface IDomainObjectFactory |
|||
{ |
|||
IAggregate CreateNew(Type type, Guid id); |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
// ==========================================================================
|
|||
// IDomainObjectRepository.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS.Commands |
|||
{ |
|||
public interface IDomainObjectRepository |
|||
{ |
|||
Task<TDomainObject> GetByIdAsync<TDomainObject>(Guid id, int version = 0) where TDomainObject : class, IAggregate; |
|||
|
|||
Task SaveAsync(IAggregate domainObject, Guid commitId); |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
// ==========================================================================
|
|||
// InMemoryCommandBus.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS.Commands |
|||
{ |
|||
public sealed class InMemoryCommandBus : ICommandBus |
|||
{ |
|||
private readonly IDomainObjectFactory factory; |
|||
private readonly IDomainObjectRepository repository; |
|||
private readonly IEnumerable<ICommandHandler> handlers; |
|||
|
|||
public InMemoryCommandBus( |
|||
IDomainObjectRepository repository, |
|||
IDomainObjectFactory factory, |
|||
IEnumerable<ICommandHandler> handlers) |
|||
{ |
|||
Guard.NotNull(factory, nameof(factory)); |
|||
Guard.NotNull(handlers, nameof(handlers)); |
|||
Guard.NotNull(repository, nameof(repository)); |
|||
|
|||
this.factory = factory; |
|||
this.handlers = handlers; |
|||
this.repository = repository; |
|||
} |
|||
|
|||
public async Task PublishAsync(ICommand command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
var context = new CommandContext(factory, repository, command); |
|||
|
|||
foreach (var handler in handlers) |
|||
{ |
|||
try |
|||
{ |
|||
var isHandled = await handler.HandleAsync(context); |
|||
|
|||
if (isHandled) |
|||
{ |
|||
context.MarkSucceeded(); |
|||
} |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
context.MarkFailed(e); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
// ==========================================================================
|
|||
// IEventConsumer.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS.Events |
|||
{ |
|||
public interface IEventConsumer |
|||
{ |
|||
void On(Envelope<IEvent> @event); |
|||
} |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
// ==========================================================================
|
|||
// ActionDispatcher.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
|
|||
namespace PinkParrot.Infrastructure.Dispatching |
|||
{ |
|||
public sealed class ActionContextDispatcher<TTarget, TIn, TContext> |
|||
{ |
|||
private static readonly Dictionary<Type, Action<TTarget, object, TContext>> Handlers; |
|||
|
|||
static ActionContextDispatcher() |
|||
{ |
|||
Handlers = |
|||
typeof(TTarget) |
|||
.GetMethods() |
|||
.Where(Helper.HasRightName) |
|||
.Where(Helper.HasRightParameters<TIn, TContext>) |
|||
.Select(ActionContextDispatcherFactory.CreateActionHandler<TTarget, TContext>) |
|||
.ToDictionary(h => h.Item1, h => h.Item2); |
|||
} |
|||
|
|||
public static bool Dispatch(TTarget target, TIn input, TContext context) |
|||
{ |
|||
Action<TTarget, object, TContext> handler; |
|||
|
|||
if (!Handlers.TryGetValue(input.GetType(), out handler)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
handler(target, input, context); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
// ==========================================================================
|
|||
// ActionHandlerFactory.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Reflection; |
|||
|
|||
namespace PinkParrot.Infrastructure.Dispatching |
|||
{ |
|||
internal class ActionContextDispatcherFactory |
|||
{ |
|||
public static Tuple<Type, Action<TTarget, object, TContext>> CreateActionHandler<TTarget, TContext>(MethodInfo methodInfo) |
|||
{ |
|||
var inputType = methodInfo.GetParameters()[0].ParameterType; |
|||
|
|||
var factoryMethod = |
|||
typeof(ActionContextDispatcherFactory) |
|||
.GetMethod("Factory", BindingFlags.Static | BindingFlags.NonPublic) |
|||
.MakeGenericMethod(typeof(TTarget), inputType, typeof(TContext)); |
|||
|
|||
var handler = factoryMethod.Invoke(null, new object[] { methodInfo }); |
|||
|
|||
return new Tuple<Type, Action<TTarget, object, TContext>>(inputType, (Action<TTarget, object, TContext>)handler); |
|||
} |
|||
|
|||
private static Action<TTarget, object, TContext> Factory<TTarget, TIn, TContext>(MethodInfo methodInfo) |
|||
{ |
|||
var type = typeof(Action<TTarget, TIn, TContext>); |
|||
|
|||
var handler = (Action<TTarget, TIn, TContext>)methodInfo.CreateDelegate(type); |
|||
|
|||
return (target, input, context) => handler(target, (TIn)input, context); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
// ==========================================================================
|
|||
// ActionDispatcher.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
|
|||
namespace PinkParrot.Infrastructure.Dispatching |
|||
{ |
|||
public sealed class ActionDispatcher<TTarget, TIn> |
|||
{ |
|||
private static readonly Dictionary<Type, Action<TTarget, object>> Handlers; |
|||
|
|||
static ActionDispatcher() |
|||
{ |
|||
Handlers = |
|||
typeof(TTarget) |
|||
.GetMethods() |
|||
.Where(Helper.HasRightName) |
|||
.Where(Helper.HasRightParameters<TIn>) |
|||
.Select(ActionDispatcherFactory.CreateActionHandler<TTarget>) |
|||
.ToDictionary(h => h.Item1, h => h.Item2); |
|||
} |
|||
|
|||
public static bool Dispatch(TTarget target, TIn item) |
|||
{ |
|||
Action<TTarget, object> handler; |
|||
|
|||
if (!Handlers.TryGetValue(item.GetType(), out handler)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
handler(target, item); |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
// ==========================================================================
|
|||
// ActionHandlerFactory.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Reflection; |
|||
|
|||
namespace PinkParrot.Infrastructure.Dispatching |
|||
{ |
|||
internal class ActionDispatcherFactory |
|||
{ |
|||
public static Tuple<Type, Action<T, object>> CreateActionHandler<T>(MethodInfo methodInfo) |
|||
{ |
|||
var inputType = methodInfo.GetParameters()[0].ParameterType; |
|||
|
|||
var factoryMethod = |
|||
typeof(ActionDispatcherFactory) |
|||
.GetMethod("Factory", BindingFlags.Static | BindingFlags.NonPublic) |
|||
.MakeGenericMethod(typeof(T), inputType); |
|||
|
|||
var handler = factoryMethod.Invoke(null, new object[] { methodInfo }); |
|||
|
|||
return new Tuple<Type, Action<T, object>>(inputType, (Action<T, object>)handler); |
|||
} |
|||
|
|||
private static Action<TTarget, object> Factory<TTarget, TIn>(MethodInfo methodInfo) |
|||
{ |
|||
var type = typeof(Action<TTarget, TIn>); |
|||
|
|||
var handler = (Action<TTarget, TIn>)methodInfo.CreateDelegate(type); |
|||
|
|||
return (target, input) => handler(target, (TIn)input); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
// ==========================================================================
|
|||
// DispatchExtensions.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Threading.Tasks; |
|||
|
|||
namespace PinkParrot.Infrastructure.Dispatching |
|||
{ |
|||
public static class DispatchExtensions |
|||
{ |
|||
public static bool DispatchAction<TTarget, TIn>(this TTarget target, TIn input) |
|||
{ |
|||
return ActionDispatcher<TTarget, TIn>.Dispatch(target, input); |
|||
} |
|||
|
|||
public static bool DispatchAction<TTarget, TIn, TContext>(this TTarget target, TIn input, TContext context) |
|||
{ |
|||
return ActionContextDispatcher<TTarget, TIn, TContext>.Dispatch(target, input, context); |
|||
} |
|||
|
|||
public static async Task<bool> DispatchActionAsync<TTarget, TIn>(this TTarget target, TIn input) |
|||
{ |
|||
var task = FuncDispatcher<TTarget, TIn, Task>.Dispatch(target, input); |
|||
|
|||
if (task == null) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
await task; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public static async Task<bool> DispatchActionAsync<TTarget, TIn, TContext>(this TTarget target, TIn input, TContext context) |
|||
{ |
|||
var task = FuncContextDispatcher<TTarget, TIn, TContext, Task>.Dispatch(target, input, context); |
|||
|
|||
if (task == null) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
await task; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
public static TOut DispatchFunc<TTarget, TIn, TOut>(this TTarget target, TIn input, TOut fallback) |
|||
{ |
|||
var result = FuncDispatcher<TTarget, TIn, TOut>.Dispatch(target, input); |
|||
|
|||
return Equals(result, default(TOut)) ? fallback : result; |
|||
} |
|||
|
|||
public static TOut DispatchFunc<TTarget, TIn, TContext, TOut>(this TTarget target, TIn input, TContext context, TOut fallback) |
|||
{ |
|||
var result = FuncContextDispatcher<TTarget, TIn, TContext, TOut>.Dispatch(target, input, context); |
|||
|
|||
return Equals(result, default(TOut)) ? fallback : result; |
|||
} |
|||
|
|||
public static Task<TOut> DispatchFuncAsync<TTarget, TIn, TOut>(this TTarget target, TIn input, TOut fallback) |
|||
{ |
|||
var result = FuncDispatcher<TTarget, TIn, Task<TOut>>.Dispatch(target, input); |
|||
|
|||
return result ?? Task.FromResult(fallback); |
|||
} |
|||
|
|||
public static Task<TOut> DispatchFuncAsync<TTarget, TIn, TContext, TOut>(this TTarget target, TIn input, TContext context, TOut fallback) |
|||
{ |
|||
var result = FuncContextDispatcher<TTarget, TIn, TContext, Task<TOut>>.Dispatch(target, input, context); |
|||
|
|||
return result ?? Task.FromResult(fallback); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
// ==========================================================================
|
|||
// FuncDispatcher.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
|
|||
namespace PinkParrot.Infrastructure.Dispatching |
|||
{ |
|||
public sealed class FuncContextDispatcher<TTarget, TIn, TContext, TOut> |
|||
{ |
|||
private static readonly Dictionary<Type, Func<TTarget, object, TContext, TOut>> Handlers; |
|||
|
|||
static FuncContextDispatcher() |
|||
{ |
|||
Handlers = |
|||
typeof(TTarget) |
|||
.GetMethods() |
|||
.Where(Helper.HasRightName) |
|||
.Where(Helper.HasRightParameters<TIn, TContext>) |
|||
.Where(Helper.HasRightReturnType<TOut>) |
|||
.Select(FuncContextDispatcherFactory.CreateFuncHandler<TTarget, TContext, TOut >) |
|||
.ToDictionary(h => h.Item1, h => h.Item2); |
|||
} |
|||
|
|||
public static TOut Dispatch(TTarget target, TIn item, TContext context) |
|||
{ |
|||
Func<TTarget, object, TContext, TOut > handler; |
|||
|
|||
if (Handlers.TryGetValue(item.GetType(), out handler)) |
|||
{ |
|||
return handler(target, item, context); |
|||
} |
|||
|
|||
return default(TOut); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
// ==========================================================================
|
|||
// HandlerFactory.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Reflection; |
|||
|
|||
namespace PinkParrot.Infrastructure.Dispatching |
|||
{ |
|||
internal static class FuncContextDispatcherFactory |
|||
{ |
|||
public static Tuple<Type, Func<TTarget, object, TContext, TOut>> CreateFuncHandler<TTarget, TContext, TOut>(MethodInfo methodInfo) |
|||
{ |
|||
var inputType = methodInfo.GetParameters()[0].ParameterType; |
|||
|
|||
var factoryMethod = |
|||
typeof(FuncContextDispatcherFactory) |
|||
.GetMethod("Factory", BindingFlags.Static | BindingFlags.NonPublic) |
|||
.MakeGenericMethod(typeof(TTarget), inputType, typeof(TContext), methodInfo.ReturnType); |
|||
|
|||
var handler = factoryMethod.Invoke(null, new object[] { methodInfo }); |
|||
|
|||
return new Tuple<Type, Func<TTarget, object, TContext, TOut>>(inputType, (Func<TTarget, object, TContext, TOut>)handler); |
|||
} |
|||
|
|||
private static Func<TTarget, object, TContext, TOut> Factory<TTarget, TIn, TContext, TOut>(MethodInfo methodInfo) |
|||
{ |
|||
var type = typeof(Func<TTarget, TIn, TContext, TOut>); |
|||
|
|||
var handler = (Func<TTarget, TIn, TContext, TOut>)methodInfo.CreateDelegate(type); |
|||
|
|||
return (target, input, context) => handler(target, (TIn)input, context); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
// ==========================================================================
|
|||
// FuncDispatcher.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
|
|||
namespace PinkParrot.Infrastructure.Dispatching |
|||
{ |
|||
public sealed class FuncDispatcher<TTarget, TIn, TOut> |
|||
{ |
|||
private static readonly Dictionary<Type, Func<TTarget, object, TOut>> Handlers; |
|||
|
|||
static FuncDispatcher() |
|||
{ |
|||
Handlers = |
|||
typeof(TTarget) |
|||
.GetMethods() |
|||
.Where(Helper.HasRightName) |
|||
.Where(Helper.HasRightParameters<TIn>) |
|||
.Where(Helper.HasRightReturnType<TOut>) |
|||
.Select(FuncDispatcherFactory.CreateFuncHandler<TTarget, TOut>) |
|||
.ToDictionary(h => h.Item1, h => h.Item2); |
|||
} |
|||
|
|||
public static TOut Dispatch(TTarget target, TIn item) |
|||
{ |
|||
Func<TTarget, object, TOut> handler; |
|||
|
|||
if (Handlers.TryGetValue(item.GetType(), out handler)) |
|||
{ |
|||
return handler(target, item); |
|||
} |
|||
|
|||
return default(TOut); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
// ==========================================================================
|
|||
// HandlerFactory.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Reflection; |
|||
|
|||
namespace PinkParrot.Infrastructure.Dispatching |
|||
{ |
|||
internal static class FuncDispatcherFactory |
|||
{ |
|||
public static Tuple<Type, Func<TTarget, object, TReturn>> CreateFuncHandler<TTarget, TReturn>(MethodInfo methodInfo) |
|||
{ |
|||
var inputType = methodInfo.GetParameters()[0].ParameterType; |
|||
|
|||
var factoryMethod = |
|||
typeof(FuncDispatcherFactory) |
|||
.GetMethod("Factory", BindingFlags.Static | BindingFlags.NonPublic) |
|||
.MakeGenericMethod(typeof(TTarget), inputType, methodInfo.ReturnType); |
|||
|
|||
var handler = factoryMethod.Invoke(null, new object[] { methodInfo }); |
|||
|
|||
return new Tuple<Type, Func<TTarget, object, TReturn>>(inputType, (Func<TTarget, object, TReturn>)handler); |
|||
} |
|||
|
|||
private static Func<TTarget, object, TReturn> Factory<TTarget, TIn, TReturn>(MethodInfo methodInfo) |
|||
{ |
|||
var type = typeof(Func<TTarget, TIn, TReturn>); |
|||
|
|||
var handler = (Func<TTarget, TIn, TReturn>)methodInfo.CreateDelegate(type); |
|||
|
|||
return (target, input) => handler(target, (TIn)input); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
// ==========================================================================
|
|||
// Helper.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Reflection; |
|||
|
|||
namespace PinkParrot.Infrastructure.Dispatching |
|||
{ |
|||
internal static class Helper |
|||
{ |
|||
public static bool HasRightName(MethodInfo method) |
|||
{ |
|||
return method.Name == "On"; |
|||
} |
|||
|
|||
public static bool HasRightReturnType<TOut>(MethodInfo method) |
|||
{ |
|||
return method.ReturnType == typeof(TOut); |
|||
} |
|||
|
|||
public static bool HasRightParameters<TIn>(MethodInfo method) |
|||
{ |
|||
var parameters = method.GetParameters(); |
|||
|
|||
return parameters.Length == 1 && typeof(TIn).IsAssignableFrom(parameters[0].ParameterType); |
|||
} |
|||
|
|||
public static bool HasRightParameters<TIn, TContext>(MethodInfo method) |
|||
{ |
|||
var parameters = method.GetParameters(); |
|||
|
|||
return parameters.Length == 2 && typeof(TIn).IsAssignableFrom(parameters[0].ParameterType) && parameters[1].ParameterType == typeof(TContext); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using System; |
|||
|
|||
namespace PinkParrot.Infrastructure.CQRS.Commands |
|||
{ |
|||
public interface ICommandContext |
|||
{ |
|||
ICommand Command { get; } |
|||
Exception Exception { get; } |
|||
IDomainObjectFactory Factory { get; } |
|||
bool IsFailed { get; } |
|||
bool IsHandled { get; } |
|||
bool IsSucceeded { get; } |
|||
IDomainObjectRepository Repository { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
// ==========================================================================
|
|||
// JsonPropertiesBagConverter.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Newtonsoft.Json; |
|||
using NodaTime; |
|||
using NodaTime.Extensions; |
|||
|
|||
namespace PinkParrot.Infrastructure.Json |
|||
{ |
|||
public sealed class PropertiesBagConverter : JsonConverter |
|||
{ |
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return objectType == typeof(PropertiesBag); |
|||
} |
|||
|
|||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
|||
{ |
|||
var properties = new PropertiesBag(); |
|||
|
|||
while (reader.Read()) |
|||
{ |
|||
if (reader.TokenType != JsonToken.PropertyName) |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
var key = reader.Value.ToString(); |
|||
|
|||
reader.Read(); |
|||
|
|||
var value = reader.Value; |
|||
|
|||
if (value is DateTime) |
|||
{ |
|||
properties.Set(key, ((DateTime)value).ToInstant()); |
|||
} |
|||
else |
|||
{ |
|||
properties.Set(key, value); |
|||
} |
|||
} |
|||
|
|||
return properties; |
|||
} |
|||
|
|||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) |
|||
{ |
|||
var properties = (PropertiesBag)value; |
|||
|
|||
writer.WriteStartObject(); |
|||
|
|||
foreach (var kvp in properties.Properties) |
|||
{ |
|||
writer.WritePropertyName(kvp.Key); |
|||
|
|||
if (kvp.Value.RawValue is Instant) |
|||
{ |
|||
writer.WriteValue(kvp.Value.ToString()); |
|||
} |
|||
else |
|||
{ |
|||
writer.WriteValue(kvp.Value.RawValue); |
|||
} |
|||
} |
|||
|
|||
writer.WriteEndObject(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,87 @@ |
|||
// ==========================================================================
|
|||
// ModelSchemaCommandHandler.cs
|
|||
// PinkParrot Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) PinkParrot Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using PinkParrot.Infrastructure.CQRS.Commands; |
|||
using PinkParrot.Infrastructure.Dispatching; |
|||
using PinkParrot.Write.Schema.Commands; |
|||
|
|||
namespace PinkParrot.Write.Schema |
|||
{ |
|||
public class ModelSchemaCommandHandler : ICommandHandler |
|||
{ |
|||
public Task<bool> HandleAsync(CommandContext context) |
|||
{ |
|||
return this.DispatchActionAsync(context.Command, context); |
|||
} |
|||
|
|||
protected Task On(AddModelField command, CommandContext context) |
|||
{ |
|||
return Update(command, context, schema => schema.AddField(command)); |
|||
} |
|||
|
|||
protected Task On(DeleteModelField command, CommandContext context) |
|||
{ |
|||
return Update(command, context, schema => schema.DeleteField(command)); |
|||
} |
|||
|
|||
protected Task On(DeleteModelSchema command, CommandContext context) |
|||
{ |
|||
return Update(command, context, schema => schema.Delete(command)); |
|||
} |
|||
|
|||
protected Task On(DisableModelField command, CommandContext context) |
|||
{ |
|||
return Update(command, context, schema => schema.DisableField(command)); |
|||
} |
|||
|
|||
protected Task On(EnableModelField command, CommandContext context) |
|||
{ |
|||
return Update(command, context, schema => schema.EnableField(command)); |
|||
} |
|||
|
|||
protected Task On(HideModelField command, CommandContext context) |
|||
{ |
|||
return Update(command, context, schema => schema.HideField(command)); |
|||
} |
|||
|
|||
protected Task On(ShowModelField command, CommandContext context) |
|||
{ |
|||
return Update(command, context, schema => schema.ShowField(command)); |
|||
} |
|||
|
|||
protected Task On(UpdateModelField command, CommandContext context) |
|||
{ |
|||
return Update(command, context, schema => schema.UpdateField(command)); |
|||
} |
|||
|
|||
protected Task On(UpdateModelSchema command, CommandContext context) |
|||
{ |
|||
return Update(command, context, schema => schema.Update(command)); |
|||
} |
|||
|
|||
protected Task On(CreateModelSchema command, CommandContext context) |
|||
{ |
|||
var schema = context.Factory.CreateNew<ModelSchemaDomainObject>(command.AggregateId); |
|||
|
|||
schema.Create(command); |
|||
|
|||
return context.Repository.SaveAsync(schema, Guid.NewGuid()); |
|||
} |
|||
|
|||
private async Task Update(AggregateCommand command, CommandContext context, Action<ModelSchemaDomainObject> updater) |
|||
{ |
|||
var schema = await context.Repository.GetByIdAsync<ModelSchemaDomainObject>(command.AggregateId); |
|||
|
|||
updater(schema); |
|||
|
|||
await context.Repository.SaveAsync(schema, Guid.NewGuid()); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue