Browse Source

增加样例项目

master
2017875139 3 years ago
parent
commit
eb35beee5a
  1. 6
      Easy.sln
  2. 14
      sample/Tenant.Api/DDD/Domain/Consts/TenantConnectionStringConsts.cs
  3. 9
      sample/Tenant.Api/DDD/Domain/Consts/TenantConsts.cs
  4. 11
      sample/Tenant.Api/DDD/Domain/Shared/TenantEto.cs
  5. 8
      sample/Tenant.Api/DDD/Domain/TenantAggregate/ITenantManager.cs
  6. 56
      sample/Tenant.Api/DDD/Domain/TenantAggregate/Tenant.cs
  7. 36
      sample/Tenant.Api/DDD/Domain/TenantAggregate/TenantConnectionString.cs
  8. 44
      sample/Tenant.Api/DDD/Domain/TenantAggregate/TenantManager.cs
  9. 13
      sample/Tenant.Api/DDD/Domain/TenantManagementDomainMappingProfile.cs
  10. 41
      sample/Tenant.Api/Program.cs
  11. 31
      sample/Tenant.Api/Properties/launchSettings.json
  12. 27
      sample/Tenant.Api/Tenant.Api.csproj
  13. 8
      sample/Tenant.Api/appsettings.Development.json
  14. 9
      sample/Tenant.Api/appsettings.json
  15. 24
      src/Easy.DDD.Domain/Easy/DDD/Domain/Entities/AggregateRoot.cs

6
Easy.sln

@ -25,6 +25,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Easy.Core", "src\Easy.Core\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Easy.FluentValidation", "src\Easy.FluentValidation\Easy.FluentValidation.csproj", "{8EC50AAD-EB45-402A-B474-A94EDBD342A3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tenant.Api", "sample\Tenant.Api\Tenant.Api.csproj", "{15436487-E499-45C2-9580-0C145217C8CE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -67,6 +69,10 @@ Global
{8EC50AAD-EB45-402A-B474-A94EDBD342A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8EC50AAD-EB45-402A-B474-A94EDBD342A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8EC50AAD-EB45-402A-B474-A94EDBD342A3}.Release|Any CPU.Build.0 = Release|Any CPU
{15436487-E499-45C2-9580-0C145217C8CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{15436487-E499-45C2-9580-0C145217C8CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{15436487-E499-45C2-9580-0C145217C8CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{15436487-E499-45C2-9580-0C145217C8CE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

14
sample/Tenant.Api/DDD/Domain/Consts/TenantConnectionStringConsts.cs

@ -0,0 +1,14 @@
namespace Tenant.Api.DDD.Domain.Consts;
public static class TenantConnectionStringConsts
{
/// <summary>
/// Default value: 64
/// </summary>
public static int MaxNameLength { get; set; } = 64;
/// <summary>
/// Default value: 1024
/// </summary>
public static int MaxValueLength { get; set; } = 1024;
}

9
sample/Tenant.Api/DDD/Domain/Consts/TenantConsts.cs

@ -0,0 +1,9 @@
namespace Tenant.Api.DDD.Domain.Consts;
public static class TenantConsts
{
/// <summary>
/// Default value: 64
/// </summary>
public static int MaxNameLength { get; set; } = 64;
}

11
sample/Tenant.Api/DDD/Domain/Shared/TenantEto.cs

@ -0,0 +1,11 @@
using System;
namespace Tenant.Api.DDD.Domain.Shared;
[Serializable]
public class TenantEto
{
public Guid Id { get; set; }
public string Name { get; set; }
}

8
sample/Tenant.Api/DDD/Domain/TenantAggregate/ITenantManager.cs

@ -0,0 +1,8 @@
namespace Tenant.Api.DDD.Domain.TenantAggregate;
public interface ITenantManager
{
Task<Tenant> CreateAsync(string name);
Task ChangeNameAsync(Tenant tenant, string name);
}

56
sample/Tenant.Api/DDD/Domain/TenantAggregate/Tenant.cs

@ -0,0 +1,56 @@
using Easy;
using Easy.DDD.Domain.Entities;
using Tenant.Api.DDD.Domain.Consts;
namespace Tenant.Api.DDD.Domain.TenantAggregate;
public class Tenant : AggregateRoot<Guid>
{
public virtual string Name { get; protected set; }
public virtual List<TenantConnectionString> ConnectionStrings { get; protected set; }
protected Tenant()
{
}
protected internal Tenant(Guid id, string name)
: base(id)
{
SetName(name);
ConnectionStrings = new List<TenantConnectionString>();
}
public virtual void SetConnectionString(string name, string connectionString)
{
var tenantConnectionString = ConnectionStrings.FirstOrDefault(x => x.Name == name);
if (tenantConnectionString != null)
{
tenantConnectionString.SetValue(connectionString);
}
else
{
ConnectionStrings.Add(new TenantConnectionString(Id, name, connectionString));
}
}
public virtual void RemoveConnectionString(string name)
{
var tenantConnectionString = ConnectionStrings.FirstOrDefault(x => x.Name == name);
if (tenantConnectionString != null)
{
ConnectionStrings.Remove(tenantConnectionString);
}
}
protected internal virtual void SetName(string name)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConsts.MaxNameLength);
}
}

36
sample/Tenant.Api/DDD/Domain/TenantAggregate/TenantConnectionString.cs

@ -0,0 +1,36 @@
using Easy;
using Easy.DDD.Domain.Entities;
using Tenant.Api.DDD.Domain.Consts;
namespace Tenant.Api.DDD.Domain.TenantAggregate;
public class TenantConnectionString : Entity
{
public virtual Guid TenantId { get; protected set; }
public virtual string Name { get; protected set; }
public virtual string Value { get; protected set; }
protected TenantConnectionString()
{
}
public TenantConnectionString(Guid tenantId, string name, string value)
{
TenantId = tenantId;
Name = Check.NotNullOrWhiteSpace(name, nameof(name), TenantConnectionStringConsts.MaxNameLength);
SetValue(value);
}
public virtual void SetValue(string value)
{
Value = Check.NotNullOrWhiteSpace(value, nameof(value), TenantConnectionStringConsts.MaxValueLength);
}
public override object[] GetKeys()
{
return new object[] { TenantId, Name };
}
}

44
sample/Tenant.Api/DDD/Domain/TenantAggregate/TenantManager.cs

@ -0,0 +1,44 @@
using Easy;
using Easy.DDD.Domain.Repositories;
using Easy.Guids;
using Microsoft.EntityFrameworkCore;
namespace Tenant.Api.DDD.Domain.TenantAggregate;
public class TenantManager
{
public IRepository<Tenant> TenantRepository { get; }
protected IGuidGenerator GuidGenerator { get; }
public TenantManager(IRepository<Tenant> tenantRepository)
{
TenantRepository = tenantRepository;
}
public virtual async Task<Tenant> CreateAsync(string name)
{
Check.NotNull(name, nameof(name));
await ValidateNameAsync(name);
return new Tenant(GuidGenerator.Create(), name);
}
public virtual async Task ChangeNameAsync(Tenant tenant, string name)
{
Check.NotNull(tenant, nameof(tenant));
Check.NotNull(name, nameof(name));
await ValidateNameAsync(name, tenant.Id);
tenant.SetName(name);
}
protected virtual async Task ValidateNameAsync(string name, Guid? expectedId = null)
{
var tenant = await TenantRepository
.Where(o => o.Name == name)
.Include(x => x.ConnectionStrings)
.OrderBy(t => t.Id)
.FirstOrDefaultAsync();
When.Is(tenant != null && tenant.Id != expectedId, "重复的租户名称: " + name);
}
}

13
sample/Tenant.Api/DDD/Domain/TenantManagementDomainMappingProfile.cs

@ -0,0 +1,13 @@
using AutoMapper;
using Tenant.Api.DDD.Domain.Shared;
namespace Tenant.Api.DDD.Domain;
public class TenantManagementDomainMappingProfile : Profile
{
public TenantManagementDomainMappingProfile()
{
CreateMap<TenantAggregate.Tenant, TenantEto>();
}
}

41
sample/Tenant.Api/Program.cs

@ -0,0 +1,41 @@
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateTime.Now.AddDays(index),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast");
app.Run();
internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

31
sample/Tenant.Api/Properties/launchSettings.json

@ -0,0 +1,31 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:60261",
"sslPort": 0
}
},
"profiles": {
"Tenant.Api": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5275",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

27
sample/Tenant.Api/Tenant.Api.csproj

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<!--<Nullable>enable</Nullable>-->
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="11.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Easy.Api\Easy.DDD.Application.csproj" />
<ProjectReference Include="..\..\src\Easy.DDD.Domain\Easy.DDD.Domain.csproj" />
<ProjectReference Include="..\..\src\Easy.Guids\Easy.Guids.csproj" />
<ProjectReference Include="..\..\src\Easy.Result\Easy.Result.csproj" />
<ProjectReference Include="..\..\src\Easy.Specifications\Easy.Specifications.csproj" />
<ProjectReference Include="..\..\src\Easy.Uow\Easy.Uow.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="DDD\Application\Dtos\" />
</ItemGroup>
</Project>

8
sample/Tenant.Api/appsettings.Development.json

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

9
sample/Tenant.Api/appsettings.json

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

24
src/Easy.DDD.Domain/Easy/DDD/Domain/Entities/AggregateRoot.cs

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Easy.DDD.Domain.Entities;
public abstract class AggregateRoot : Entity, IAggregateRoot
{
}
public abstract class AggregateRoot<TKey> : Entity<TKey>, IAggregateRoot<TKey>
{
protected AggregateRoot()
{
}
protected AggregateRoot(TKey id)
: base(id)
{
}
}
Loading…
Cancel
Save