Skip to content

Commit

Permalink
release: 1.0.0-alpha
Browse files Browse the repository at this point in the history
  • Loading branch information
esofar committed Nov 8, 2023
1 parent 40a1013 commit 9de96b6
Show file tree
Hide file tree
Showing 145 changed files with 5,078 additions and 1 deletion.
25 changes: 25 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[*.cs]

# CS8618: 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
dotnet_diagnostic.CS8618.severity = none
69 changes: 69 additions & 0 deletions Dddify.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.7.34221.43
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dddify", "src\Dddify\Dddify.csproj", "{DE8F5397-029E-4C9A-9660-F121DF0FC809}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{38770002-B724-45E5-BEDD-DC6E5B252596}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{4F2BDD51-DC98-44B7-AB88-8E867693C0BB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Todolist.Application", "samples\Todolist.Application\Todolist.Application.csproj", "{957C7F41-FF33-4870-8CD1-BFBE318616D8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Todolist.Domain", "samples\Todolist.Domain\Todolist.Domain.csproj", "{4B76236D-DBB2-4D69-A191-D703F6851B0A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Todolist.Infrastructure", "samples\Todolist.Infrastructure\Todolist.Infrastructure.csproj", "{A7CBA200-F160-494B-B2B5-E863640C83D0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dddify.Tests", "test\Dddify.Tests\Dddify.Tests.csproj", "{5231D115-F3F9-4252-AFF5-7E89354518D7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{6CF949D7-D6A1-4CBC-B9BF-338C703C0B1F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Todolist.WebHost", "samples\Todolist.WebHost\Todolist.WebHost.csproj", "{47A25EBB-99BF-4217-9C29-3C8A934E72AB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DE8F5397-029E-4C9A-9660-F121DF0FC809}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE8F5397-029E-4C9A-9660-F121DF0FC809}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE8F5397-029E-4C9A-9660-F121DF0FC809}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE8F5397-029E-4C9A-9660-F121DF0FC809}.Release|Any CPU.Build.0 = Release|Any CPU
{957C7F41-FF33-4870-8CD1-BFBE318616D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{957C7F41-FF33-4870-8CD1-BFBE318616D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{957C7F41-FF33-4870-8CD1-BFBE318616D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{957C7F41-FF33-4870-8CD1-BFBE318616D8}.Release|Any CPU.Build.0 = Release|Any CPU
{4B76236D-DBB2-4D69-A191-D703F6851B0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4B76236D-DBB2-4D69-A191-D703F6851B0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B76236D-DBB2-4D69-A191-D703F6851B0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B76236D-DBB2-4D69-A191-D703F6851B0A}.Release|Any CPU.Build.0 = Release|Any CPU
{A7CBA200-F160-494B-B2B5-E863640C83D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7CBA200-F160-494B-B2B5-E863640C83D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7CBA200-F160-494B-B2B5-E863640C83D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7CBA200-F160-494B-B2B5-E863640C83D0}.Release|Any CPU.Build.0 = Release|Any CPU
{5231D115-F3F9-4252-AFF5-7E89354518D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5231D115-F3F9-4252-AFF5-7E89354518D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5231D115-F3F9-4252-AFF5-7E89354518D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5231D115-F3F9-4252-AFF5-7E89354518D7}.Release|Any CPU.Build.0 = Release|Any CPU
{47A25EBB-99BF-4217-9C29-3C8A934E72AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{47A25EBB-99BF-4217-9C29-3C8A934E72AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{47A25EBB-99BF-4217-9C29-3C8A934E72AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{47A25EBB-99BF-4217-9C29-3C8A934E72AB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{DE8F5397-029E-4C9A-9660-F121DF0FC809} = {38770002-B724-45E5-BEDD-DC6E5B252596}
{957C7F41-FF33-4870-8CD1-BFBE318616D8} = {4F2BDD51-DC98-44B7-AB88-8E867693C0BB}
{4B76236D-DBB2-4D69-A191-D703F6851B0A} = {4F2BDD51-DC98-44B7-AB88-8E867693C0BB}
{A7CBA200-F160-494B-B2B5-E863640C83D0} = {4F2BDD51-DC98-44B7-AB88-8E867693C0BB}
{5231D115-F3F9-4252-AFF5-7E89354518D7} = {6CF949D7-D6A1-4CBC-B9BF-338C703C0B1F}
{47A25EBB-99BF-4217-9C29-3C8A934E72AB} = {4F2BDD51-DC98-44B7-AB88-8E867693C0BB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {852C1AD4-4F5F-4CAA-B76F-5446843A7D9B}
EndGlobalSection
EndGlobal
40 changes: 39 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,40 @@
# dddify
Dddify
=======

[![NuGet](https://img.shields.io/nuget/esofar/dddify.svg)](https://www.nuget.org/packages/dddify)
[![NuGet](https://img.shields.io/nuget/vpre/dddify.svg)](https://www.nuget.org/packages/dddify)

A lightweight framework that practices Domain-Driven Design approach for building modern applications on ASP.NET Core.

### Install

You should install [Dddify with NuGet](https://www.nuget.org/packages/dddify):

Install-Package Dddify

Or via the .NET Core command line interface:

dotnet add package Dddify

Either commands, from Package Manager Console or .NET Core CLI, will download and install Dddify and all required dependencies. Currently only supports the target framework .NET 7.


### Usage

Add the following code to the Program.cs file.

builder.Services.AddDddify(cfg =>
{
// Sets the DateTimeKind for date and time values.
cfg.WithDateTimeKind(DateTimeKind.Utc);

// Sets the type of sequential GUID to be used.
cfg.WithSequentialGuidType(SequentialGuidType.SequentialAsString);

// Adds the JSON localization extension
cfg.UseJsonLocalization();

// Adds the API result wrapper extension.
cfg.UseApiResultWrapper();
});

9 changes: 9 additions & 0 deletions samples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Todolist

A simple to-do list application that currently only implements a Web API.

Launch the app:
```
cd samples\Todolist.WebHost
dotnet watch run
```
38 changes: 38 additions & 0 deletions samples/Todolist.Application/Commands/CreateTodoListCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using MediatR;

namespace Todolist.Application.Commands;

public record CreateTodoListCommand(string Title, TodoListColour Colour) : ICommand;

public class CreateTodoListCommandValidator : AbstractValidator<CreateTodoListCommand>
{
public CreateTodoListCommandValidator()
{
RuleFor(v => v.Title).NotEmpty().MaximumLength(100);
RuleFor(v => v.Colour).NotEmpty().Must(colour => TodoListColour.SupportedColours.Any(c => c.Code == colour.Code));
}
}

public class CreateTodoListCommandHandler : ICommandHandler<CreateTodoListCommand>
{
private readonly IApplicationDbContext _context;

public CreateTodoListCommandHandler(IApplicationDbContext context)
{
_context = context;
}

public async Task Handle(CreateTodoListCommand command, CancellationToken cancellationToken)
{
if (await _context.TodoLists.AnyAsync(c => c.Title == command.Title, cancellationToken))
{
throw new TodoListDuplicateException(command.Title);
}

var todoList = new TodoList(command.Title, command.Colour);

await _context.TodoLists.AddAsync(todoList, cancellationToken);

await _context.SaveChangesAsync(cancellationToken);
}
}
44 changes: 44 additions & 0 deletions samples/Todolist.Application/Commands/CreateTodoListItemCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
namespace Todolist.Application.Commands;

public record CreateTodoListItemCommand(
Guid TodoListId,
string Note,
string Priority) : ICommand;

public class CreateTodoListItemCommandValidator : AbstractValidator<CreateTodoListItemCommand>
{
public CreateTodoListItemCommandValidator()
{
RuleFor(c => c.TodoListId).NotEmpty();
RuleFor(c => c.Note).NotEmpty().MaximumLength(200);
RuleFor(c => c.Priority).NotEmpty().IsEnumName(typeof(TodoListItemPriority), false);
}
}

public class CreateTodoListItemCommandHandler : ICommandHandler<CreateTodoListItemCommand>
{
private readonly IApplicationDbContext _context;

public CreateTodoListItemCommandHandler(IApplicationDbContext context)
{
_context = context;
}

public async Task Handle(CreateTodoListItemCommand command, CancellationToken cancellationToken)
{
var todoList = await _context.TodoLists
.Include(c => c.Items)
.FirstOrDefaultAsync(c => c.Id == command.TodoListId, cancellationToken);

if (todoList is null)
{
throw new TodoListNotFoundException(command.TodoListId);
}

todoList.AddItem(
command.Note,
command.Priority.ToEnum<TodoListItemPriority>());

await _context.SaveChangesAsync(cancellationToken);
}
}
35 changes: 35 additions & 0 deletions samples/Todolist.Application/Commands/DeleteTodoListCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace Todolist.Application.Commands;

public record DeleteTodoListCommand(Guid Id) : ICommand;

public class DeleteTodoListCommandValidator : AbstractValidator<DeleteTodoListCommand>
{
public DeleteTodoListCommandValidator()
{
RuleFor(c => c.Id).NotEmpty();
}
}

public class DeleteTodoCommandHandler : ICommandHandler<DeleteTodoListCommand>
{
private readonly IApplicationDbContext _context;

public DeleteTodoCommandHandler(IApplicationDbContext context)
{
_context = context;
}

public async Task Handle(DeleteTodoListCommand command, CancellationToken cancellationToken)
{
var todoList = await _context.TodoLists.FirstOrDefaultAsync(c => c.Id == command.Id, cancellationToken);

if (todoList is null)
{
throw new TodoListNotFoundException(command.Id);
}

_context.TodoLists.Remove(todoList);

await _context.SaveChangesAsync(cancellationToken);
}
}
38 changes: 38 additions & 0 deletions samples/Todolist.Application/Commands/DeleteTodoListItemCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Todolist.Application.Commands;

public record DeleteTodoListItemCommand(Guid TodoListId, Guid TodoListItemId) : ICommand;

public class DeleteTodoListItemCommandValidator : AbstractValidator<DeleteTodoListItemCommand>
{
public DeleteTodoListItemCommandValidator()
{
RuleFor(c => c.TodoListId).NotEmpty();
RuleFor(c => c.TodoListItemId).NotEmpty();
}
}

public class DeleteTodoListItemCommandHandler : ICommandHandler<DeleteTodoListItemCommand>
{
private readonly IApplicationDbContext _context;

public DeleteTodoListItemCommandHandler(IApplicationDbContext context)
{
_context = context;
}

public async Task Handle(DeleteTodoListItemCommand command, CancellationToken cancellationToken)
{
var todoList = await _context.TodoLists
.Include(c => c.Items)
.FirstOrDefaultAsync(c => c.Id == command.TodoListId, cancellationToken);

if (todoList is null)
{
throw new TodoListNotFoundException(command.TodoListId);
}

todoList.DeleteItem(command.TodoListItemId);

await _context.SaveChangesAsync(cancellationToken);
}
}
38 changes: 38 additions & 0 deletions samples/Todolist.Application/Commands/SortTodoListItemCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Todolist.Application.Commands;

public record SortTodoListItemCommand(Guid TodoListId, Guid[] TodoListItemIds) : ICommand;

public class SortTodoListItemCommandValidator : AbstractValidator<SortTodoListItemCommand>
{
public SortTodoListItemCommandValidator()
{
RuleFor(c => c.TodoListId).NotEmpty();
RuleFor(c => c.TodoListItemIds).NotEmpty();
}
}

public class SortTodoListItemCommandHandler : ICommandHandler<SortTodoListItemCommand>
{
private readonly IApplicationDbContext _context;

public SortTodoListItemCommandHandler(IApplicationDbContext context)
{
_context = context;
}

public async Task Handle(SortTodoListItemCommand command, CancellationToken cancellationToken)
{
var todoList = await _context.TodoLists
.Include(c => c.Items)
.FirstOrDefaultAsync(c => c.Id == command.TodoListId, cancellationToken);

if (todoList is null)
{
throw new TodoListNotFoundException(command.TodoListId);
}

todoList.SortItems(command.TodoListItemIds);

await _context.SaveChangesAsync(cancellationToken);
}
}
37 changes: 37 additions & 0 deletions samples/Todolist.Application/Commands/UpdateTodoListCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
namespace Todolist.Application.Commands;

public record UpdateTodoListCommand(Guid Id, string Title, TodoListColour Colour) : ICommand;

public class UpdateTodoListCommandValidator : AbstractValidator<UpdateTodoListCommand>
{
public UpdateTodoListCommandValidator()
{
RuleFor(c => c.Id).Empty();
RuleFor(v => v.Title).NotEmpty().MaximumLength(100);
RuleFor(v => v.Colour).NotEmpty().Must(colour => TodoListColour.SupportedColours.Any(c => c.Code == colour.Code));
}
}

public class UpdateTodoListCommandHandler : ICommandHandler<UpdateTodoListCommand>
{
private readonly IApplicationDbContext _context;

public UpdateTodoListCommandHandler(IApplicationDbContext context)
{
_context = context;
}

public async Task Handle(UpdateTodoListCommand command, CancellationToken cancellationToken)
{
var todoList = await _context.TodoLists.FirstOrDefaultAsync(c => c.Id == command.Id, cancellationToken);

if (todoList is null)
{
throw new TodoListNotFoundException(command.Id);
}

todoList.Update(command.Title, command.Colour);

await _context.SaveChangesAsync(cancellationToken);
}
}
Loading

0 comments on commit 9de96b6

Please sign in to comment.