diff --git a/samples/apis/Order.Api/Startup.cs b/samples/apis/Order.Api/Startup.cs index 02aa01f..b07cbdc 100644 --- a/samples/apis/Order.Api/Startup.cs +++ b/samples/apis/Order.Api/Startup.cs @@ -30,7 +30,7 @@ namespace ServiceA { services.AddControllers(); - services.AddComteckReliableMessage(option => + services.AddPoleReliableMessage(option => { option.AddMasstransitRabbitmq(rabbitoption => { diff --git a/samples/apis/Product.Api/Application/Command/AddProductTypeCommand.cs b/samples/apis/Product.Api/Application/Command/AddProductTypeCommand.cs new file mode 100644 index 0000000..b64b045 --- /dev/null +++ b/samples/apis/Product.Api/Application/Command/AddProductTypeCommand.cs @@ -0,0 +1,15 @@ +using Pole.Application.Cqrs; +using Pole.Grpc.ExtraType; +using PoleSample.Apis.Product; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Product.Api.Application.Command +{ + public class AddProductTypeCommand: ICommand + { + public AddProductTypeRequest Request { get; set; } + } +} diff --git a/samples/apis/Product.Api/Application/Command/CommandHandler/AddProductTypeCommandHandler.cs b/samples/apis/Product.Api/Application/Command/CommandHandler/AddProductTypeCommandHandler.cs new file mode 100644 index 0000000..679cf4e --- /dev/null +++ b/samples/apis/Product.Api/Application/Command/CommandHandler/AddProductTypeCommandHandler.cs @@ -0,0 +1,37 @@ +using NewArchitectureLab.Apps.Product; +using Pole.Application.Cqrs; +using Pole.Grpc.ExtraType; +using PoleSample.Apis.Product; +using Product.Api.Domain.Event; +using Product.Api.Domain.ProductTypeAggregate; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Product.Api.Application.Command.CommandHandler +{ + public class AddProductTypeCommandHandler : ICommandHandler + { + private readonly IProductTypeRepository _productTypeRepository; + public AddProductTypeCommandHandler(IProductTypeRepository productTypeRepository) + { + _productTypeRepository = productTypeRepository; + } + public async Task Handle(AddProductTypeCommand request, CancellationToken cancellationToken) + { + var productType = new Domain.ProductTypeAggregate.ProductType(request.Request.Id, request.Request.Name); + + + _productTypeRepository.Add(productType); + ProductTypeAddedDomainEvent productTypeAddedDomainEvent = new ProductTypeAddedDomainEvent + { + ProductTypeId = productType.Id, + ProductTypeName = productType.Name + }; + productType.AddDomainEvent(productTypeAddedDomainEvent); + return await _productTypeRepository.UnitOfWork.CompeleteAsync(); + } + } +} diff --git a/samples/apis/Product.Api/Application/DomainEventHandler/AddDefaultProductWhenProductTypeAddedDomainEventHandler.cs b/samples/apis/Product.Api/Application/DomainEventHandler/AddDefaultProductWhenProductTypeAddedDomainEventHandler.cs new file mode 100644 index 0000000..e5568d6 --- /dev/null +++ b/samples/apis/Product.Api/Application/DomainEventHandler/AddDefaultProductWhenProductTypeAddedDomainEventHandler.cs @@ -0,0 +1,28 @@ +using Pole.Domain; +using Product.Api.Domain.Event; +using Product.Api.Domain.ProductAggregate; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Product.Api.Application.DomainEventHandler +{ + public class AddDefaultProductWhenProductTypeAddedDomainEventHandler : IDomainEventHandler + { + private readonly IProductRepository _productRepository; + public AddDefaultProductWhenProductTypeAddedDomainEventHandler(IProductRepository productRepository) + { + _productRepository = productRepository; + } + + public async Task Handle(ProductTypeAddedDomainEvent request, CancellationToken cancellationToken) + { + Product.Api.Domain.ProductAggregate.Product product = new Product.Api.Domain.ProductAggregate.Product(Guid.NewGuid().ToString("N"), request.ProductTypeName, 100, request.ProductTypeId); + _productRepository.Add(product); + return await _productRepository.UnitOfWork.CompeleteAsync(); + + } + } +} diff --git a/samples/apis/Product.Api/Domain/ProductAggregate/IProductRepository.cs b/samples/apis/Product.Api/Domain/AggregatesModel/ProductAggregate/IProductRepository.cs similarity index 100% rename from samples/apis/Product.Api/Domain/ProductAggregate/IProductRepository.cs rename to samples/apis/Product.Api/Domain/AggregatesModel/ProductAggregate/IProductRepository.cs diff --git a/samples/apis/Product.Api/Domain/AggregatesModel/ProductAggregate/Product.cs b/samples/apis/Product.Api/Domain/AggregatesModel/ProductAggregate/Product.cs new file mode 100644 index 0000000..1feda2c --- /dev/null +++ b/samples/apis/Product.Api/Domain/AggregatesModel/ProductAggregate/Product.cs @@ -0,0 +1,22 @@ +using Pole.Domain; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Product.Api.Domain.ProductAggregate +{ + public class Product : Entity, IAggregateRoot + { + public Product(string id ,string name,long price, string productTypeId) + { + Id = id; + Name = name; + Price = price; + ProductTypeId = productTypeId; + } + public string Name { get;private set; } + public long Price { get;private set; } + public string ProductTypeId { get;private set; } + } +} diff --git a/samples/apis/Product.Api/Domain/ProductTypeAggregate/ProductType.cs b/samples/apis/Product.Api/Domain/AggregatesModel/ProductTypeAggregate/IProductTypeRepository.cs similarity index 86% rename from samples/apis/Product.Api/Domain/ProductTypeAggregate/ProductType.cs rename to samples/apis/Product.Api/Domain/AggregatesModel/ProductTypeAggregate/IProductTypeRepository.cs index 6b382a1..0c66155 100644 --- a/samples/apis/Product.Api/Domain/ProductTypeAggregate/ProductType.cs +++ b/samples/apis/Product.Api/Domain/AggregatesModel/ProductTypeAggregate/IProductTypeRepository.cs @@ -6,8 +6,7 @@ using System.Threading.Tasks; namespace Product.Api.Domain.ProductTypeAggregate { - public class ProductType : Entity, IAggregateRoot + public interface IProductTypeRepository:IRepository { - public string Name { get; set; } } } diff --git a/samples/apis/Product.Api/Domain/AggregatesModel/ProductTypeAggregate/ProductType.cs b/samples/apis/Product.Api/Domain/AggregatesModel/ProductTypeAggregate/ProductType.cs new file mode 100644 index 0000000..060ab03 --- /dev/null +++ b/samples/apis/Product.Api/Domain/AggregatesModel/ProductTypeAggregate/ProductType.cs @@ -0,0 +1,18 @@ +using Pole.Domain; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Product.Api.Domain.ProductTypeAggregate +{ + public class ProductType : Entity, IAggregateRoot + { + public ProductType(string id,string name) + { + Id = id; + Name = name; + } + public string Name { get;private set; } + } +} diff --git a/samples/apis/Product.Api/Domain/ProductAggregate/Product.cs b/samples/apis/Product.Api/Domain/Event/ProductTypeAddedDomainEvent.cs similarity index 64% rename from samples/apis/Product.Api/Domain/ProductAggregate/Product.cs rename to samples/apis/Product.Api/Domain/Event/ProductTypeAddedDomainEvent.cs index 9be47c4..2822920 100644 --- a/samples/apis/Product.Api/Domain/ProductAggregate/Product.cs +++ b/samples/apis/Product.Api/Domain/Event/ProductTypeAddedDomainEvent.cs @@ -1,15 +1,15 @@ using Pole.Domain; +using PoleSample.Apis.Product; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -namespace Product.Api.Domain.ProductAggregate +namespace Product.Api.Domain.Event { - public class Product : Entity, IAggregateRoot + public class ProductTypeAddedDomainEvent: IDomainEvent { - public string Name { get; set; } - public long Price { get; set; } - public string ProductId { get; set; } + public string ProductTypeName { get; set; } + public string ProductTypeId { get; set; } } } diff --git a/samples/apis/Product.Api/Grpc/ProductTypeService.cs b/samples/apis/Product.Api/Grpc/ProductTypeService.cs new file mode 100644 index 0000000..bcdc62e --- /dev/null +++ b/samples/apis/Product.Api/Grpc/ProductTypeService.cs @@ -0,0 +1,27 @@ +using Grpc.Core; +using NewArchitectureLab.Apps.Product; +using Pole.Application.Cqrs; +using Pole.Grpc.ExtraType; +using PoleSample.Apis.Product; +using Product.Api.Application.Command; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Product.Api.Grpc +{ + public class ProductTypeService: PoleSample.Apis.Product.ProductType.ProductTypeBase + { + private readonly ICommandBus _commandBus; + public ProductTypeService(ICommandBus commandBus) + { + _commandBus = commandBus; + } + public override Task Add(AddProductTypeRequest request, ServerCallContext context) + { + var cpmmand = new AddProductTypeCommand { Request = request }; + return _commandBus.Send(cpmmand); + } + } +} diff --git a/samples/apis/Product.Api/Infrastructure/EntityConfigurations/ProductEntityTypeConfiguration.cs b/samples/apis/Product.Api/Infrastructure/EntityConfigurations/ProductEntityTypeConfiguration.cs index 6e7c125..7ac6aa8 100644 --- a/samples/apis/Product.Api/Infrastructure/EntityConfigurations/ProductEntityTypeConfiguration.cs +++ b/samples/apis/Product.Api/Infrastructure/EntityConfigurations/ProductEntityTypeConfiguration.cs @@ -15,11 +15,11 @@ namespace Product.Api.Infrastructure.EntityConfigurations builder.Property(m => m.Id).HasMaxLength(32); builder.Property(m => m.Name).HasMaxLength(256).IsRequired(); - builder.Property(m => m.ProductId).HasMaxLength(32).IsRequired(); + builder.Property(m => m.ProductTypeId).HasMaxLength(32).IsRequired(); builder.Ignore(m => m.DomainEvents); - builder.HasIndex(m => m.ProductId); + builder.HasIndex(m => m.ProductTypeId); builder.HasKey(m => m.Id); } } diff --git a/samples/apis/Product.Api/Infrastructure/ProductDbContext.cs b/samples/apis/Product.Api/Infrastructure/ProductDbContext.cs index 826db0b..95467bb 100644 --- a/samples/apis/Product.Api/Infrastructure/ProductDbContext.cs +++ b/samples/apis/Product.Api/Infrastructure/ProductDbContext.cs @@ -11,6 +11,8 @@ namespace Product.Api.Infrastructure { public class ProductDbContext : DbContextBase { + public DbSet Products { get; set; } + public DbSet ProductTypes { get; set; } public ProductDbContext(DbContextOptions options, IMediator mediator) : base(options, mediator) { @@ -21,10 +23,6 @@ namespace Product.Api.Infrastructure builder.ApplyConfiguration(new ProductEntityTypeEntityTypeConfiguration()); builder.ApplyConfiguration(new ProductTypeEntityTypeConfiguration()); - - //builder.ApplyConfiguration(new ThinkNestDirectSalesManagerEntityTypeConfiguration()); - //builder.ApplyConfiguration(new ThinkNestInDirectSalesManagerEntityTypeConfiguration()); - } } } diff --git a/samples/apis/Product.Api/Infrastructure/Repository/ProductRepository.cs b/samples/apis/Product.Api/Infrastructure/Repository/ProductRepository.cs new file mode 100644 index 0000000..af6cde3 --- /dev/null +++ b/samples/apis/Product.Api/Infrastructure/Repository/ProductRepository.cs @@ -0,0 +1,41 @@ +using Pole.Domain.UnitOfWork; +using Product.Api.Domain.ProductAggregate; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Product.Api.Infrastructure.Repository +{ + public class ProductRepository : IProductRepository + { + private readonly ProductDbContext _productDbContext; + + public ProductRepository(ProductDbContext productDbContext) + { + _productDbContext = productDbContext; + } + + public IUnitOfWork UnitOfWork => _productDbContext; + + public void Add(Domain.ProductAggregate.Product entity) + { + _productDbContext.Products.Add(entity); + } + + public void Delete(Domain.ProductAggregate.Product entity) + { + throw new NotImplementedException(); + } + + public Task Get(string id) + { + throw new NotImplementedException(); + } + + public void Update(Domain.ProductAggregate.Product entity) + { + throw new NotImplementedException(); + } + } +} diff --git a/samples/apis/Product.Api/Infrastructure/Repository/ProductTypeRepository.cs b/samples/apis/Product.Api/Infrastructure/Repository/ProductTypeRepository.cs new file mode 100644 index 0000000..5c945d5 --- /dev/null +++ b/samples/apis/Product.Api/Infrastructure/Repository/ProductTypeRepository.cs @@ -0,0 +1,40 @@ +using Pole.Domain.UnitOfWork; +using Product.Api.Domain.ProductTypeAggregate; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Product.Api.Infrastructure.Repository +{ + public class ProductTypeRepository : IProductTypeRepository + { + private readonly ProductDbContext _productDbContext; + + public ProductTypeRepository(ProductDbContext productDbContext) + { + _productDbContext = productDbContext; + } + public IUnitOfWork UnitOfWork => _productDbContext; + + public void Add(ProductType entity) + { + _productDbContext.ProductTypes.Add(entity); + } + + public void Delete(ProductType entity) + { + throw new NotImplementedException(); + } + + public Task Get(string id) + { + throw new NotImplementedException(); + } + + public void Update(ProductType entity) + { + throw new NotImplementedException(); + } + } +} diff --git a/samples/apis/Product.Api/Migrations/20200114090656_Add_Product.Designer.cs b/samples/apis/Product.Api/Migrations/20200114090656_Add_Product.Designer.cs new file mode 100644 index 0000000..f5c3fb3 --- /dev/null +++ b/samples/apis/Product.Api/Migrations/20200114090656_Add_Product.Designer.cs @@ -0,0 +1,67 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using Product.Api.Infrastructure; + +namespace Product.Api.Migrations +{ + [DbContext(typeof(ProductDbContext))] + [Migration("20200114090656_Add_Product")] + partial class Add_Product + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("Product.Api.Domain.ProductAggregate.Product", b => + { + b.Property("Id") + .HasColumnType("character varying(32)") + .HasMaxLength(32); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying(256)") + .HasMaxLength(256); + + b.Property("Price") + .HasColumnType("bigint"); + + b.Property("ProductTypeId") + .IsRequired() + .HasColumnType("character varying(32)") + .HasMaxLength(32); + + b.HasKey("Id"); + + b.HasIndex("ProductTypeId"); + + b.ToTable("Product"); + }); + + modelBuilder.Entity("Product.Api.Domain.ProductTypeAggregate.ProductType", b => + { + b.Property("Id") + .HasColumnType("character varying(32)") + .HasMaxLength(32); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying(256)") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.ToTable("ProductType"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/samples/apis/Product.Api/Migrations/20200114090656_Add_Product.cs b/samples/apis/Product.Api/Migrations/20200114090656_Add_Product.cs new file mode 100644 index 0000000..f059bdf --- /dev/null +++ b/samples/apis/Product.Api/Migrations/20200114090656_Add_Product.cs @@ -0,0 +1,69 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Product.Api.Migrations +{ + public partial class Add_Product : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_Product_ProductId", + table: "Product"); + + migrationBuilder.DropColumn( + name: "ProductId", + table: "Product"); + + migrationBuilder.AddColumn( + name: "ProductTypeId", + table: "Product", + maxLength: 32, + nullable: false, + defaultValue: ""); + + migrationBuilder.CreateTable( + name: "ProductType", + columns: table => new + { + Id = table.Column(maxLength: 32, nullable: false), + Name = table.Column(maxLength: 256, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ProductType", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_Product_ProductTypeId", + table: "Product", + column: "ProductTypeId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ProductType"); + + migrationBuilder.DropIndex( + name: "IX_Product_ProductTypeId", + table: "Product"); + + migrationBuilder.DropColumn( + name: "ProductTypeId", + table: "Product"); + + migrationBuilder.AddColumn( + name: "ProductId", + table: "Product", + type: "character varying(32)", + maxLength: 32, + nullable: false, + defaultValue: ""); + + migrationBuilder.CreateIndex( + name: "IX_Product_ProductId", + table: "Product", + column: "ProductId"); + } + } +} diff --git a/samples/apis/Product.Api/Migrations/ProductDbContextModelSnapshot.cs b/samples/apis/Product.Api/Migrations/ProductDbContextModelSnapshot.cs index 23229f6..d38d707 100644 --- a/samples/apis/Product.Api/Migrations/ProductDbContextModelSnapshot.cs +++ b/samples/apis/Product.Api/Migrations/ProductDbContextModelSnapshot.cs @@ -32,17 +32,33 @@ namespace Product.Api.Migrations b.Property("Price") .HasColumnType("bigint"); - b.Property("ProductId") + b.Property("ProductTypeId") .IsRequired() .HasColumnType("character varying(32)") .HasMaxLength(32); b.HasKey("Id"); - b.HasIndex("ProductId"); + b.HasIndex("ProductTypeId"); b.ToTable("Product"); }); + + modelBuilder.Entity("Product.Api.Domain.ProductTypeAggregate.ProductType", b => + { + b.Property("Id") + .HasColumnType("character varying(32)") + .HasMaxLength(32); + + b.Property("Name") + .IsRequired() + .HasColumnType("character varying(256)") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.ToTable("ProductType"); + }); #pragma warning restore 612, 618 } } diff --git a/samples/apis/Product.Api/Product.Api.csproj b/samples/apis/Product.Api/Product.Api.csproj index 47305a2..c1fc8f6 100644 --- a/samples/apis/Product.Api/Product.Api.csproj +++ b/samples/apis/Product.Api/Product.Api.csproj @@ -1,10 +1,12 @@  - netcoreapp3.1 - + + + + all @@ -17,10 +19,13 @@ - + + + + + - - + \ No newline at end of file diff --git a/samples/apis/Product.Api/Properties/launchSettings.json b/samples/apis/Product.Api/Properties/launchSettings.json index bf0fa92..fd7f224 100644 --- a/samples/apis/Product.Api/Properties/launchSettings.json +++ b/samples/apis/Product.Api/Properties/launchSettings.json @@ -1,27 +1,12 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:21635", - "sslPort": 0 - } - }, +{ "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, "Product.Api": { "commandName": "Project", - "launchBrowser": true, + "launchBrowser": false, "applicationUrl": "http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } -} +} \ No newline at end of file diff --git a/samples/apis/Product.Api/Startup.cs b/samples/apis/Product.Api/Startup.cs index 6743c0d..6d675f9 100644 --- a/samples/apis/Product.Api/Startup.cs +++ b/samples/apis/Product.Api/Startup.cs @@ -9,6 +9,8 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Pole.ReliableMessage.Storage.Mongodb; +using Product.Api.Grpc; using Product.Api.Infrastructure; namespace Product.Api @@ -19,8 +21,8 @@ namespace Product.Api private IWebHostEnvironment Environment { get; } public Startup(IConfiguration configuration, IWebHostEnvironment env) { - this.Configuration = configuration; - this.Environment = env; + Configuration = configuration; + Environment = env; } // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 @@ -29,7 +31,33 @@ namespace Product.Api services.AddDbContext(options => options.UseNpgsql(Configuration["postgres:main"])); - services.AddPoleDomain(); + services.AddGrpc(option=> { + if (Environment.IsDevelopment()) + { + option.EnableDetailedErrors = true; + } + }); + + services.AddPoleGrpc(this.GetType().Assembly); + + services.AddPoleReliableMessage(option => + { + option.AddMasstransitRabbitmq(rabbitoption => + { + rabbitoption.RabbitMqHostAddress = Configuration["RabbitmqConfig:HostAddress"]; + rabbitoption.RabbitMqHostUserName = Configuration["RabbitmqConfig:HostUserName"]; + rabbitoption.RabbitMqHostPassword = Configuration["RabbitmqConfig:HostPassword"]; + rabbitoption.QueueNamePrefix = Configuration["ServiceName"]; + }); + option.AddMongodb(mongodbOption => + { + mongodbOption.ServiceCollectionName = Configuration["ServiceName"]; + mongodbOption.Servers = Configuration.GetSection("MongoConfig:Servers").Get(); + }); + option.AddEventAssemblies(typeof(Startup).Assembly) + .AddEventHandlerAssemblies(typeof(Startup).Assembly); + option.NetworkInterfaceGatewayAddress = Configuration["ReliableMessageOption:NetworkInterfaceGatewayAddress"]; + }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -44,9 +72,10 @@ namespace Product.Api app.UseEndpoints(endpoints => { + endpoints.MapGrpcService(); endpoints.MapGet("/", async context => { - await context.Response.WriteAsync("Hello World!"); + await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909"); }); }); } diff --git a/samples/apis/Product.Api/appsettings.Development.json b/samples/apis/Product.Api/appsettings.Development.json index b72e5cd..2585d46 100644 --- a/samples/apis/Product.Api/appsettings.Development.json +++ b/samples/apis/Product.Api/appsettings.Development.json @@ -3,10 +3,28 @@ "LogLevel": { "Default": "Information", "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" + "Microsoft.Hosting.Lifetime": "Information", + "Grpc": "Information" } }, "postgres": { "main": "Server=192.168.0.248;Port=5432;Username=postgres;Password=comteck2020!@#;Database=Pole_samples_Product;Enlist=True;Timeout=0;Command Timeout=600;Pooling=false;MinPoolSize=20;MaxPoolSize=500;" + }, + "ServiceName": "Product", + "RabbitmqConfig": { + "HostAddress": "rabbitmq://192.168.0.248/", + "HostUserName": "comteck", + "HostPassword": "comteck3030" + }, + "MongoConfig": { + "Servers": [ + { + "Host": "192.168.0.248", + "Port": "27017" + } + ] + }, + "ReliableMessageOption": { + "NetworkInterfaceGatewayAddress": "192.168.0.1" } } diff --git a/samples/apis/Product.Api/appsettings.json b/samples/apis/Product.Api/appsettings.json index d9d9a9b..1e979d9 100644 --- a/samples/apis/Product.Api/appsettings.json +++ b/samples/apis/Product.Api/appsettings.json @@ -3,8 +3,33 @@ "LogLevel": { "Default": "Information", "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" + "Microsoft.Hosting.Lifetime": "Information", + "Grpc": "Information" } }, - "AllowedHosts": "*" + "postgres": { + "main": "Server=192.168.0.248;Port=5432;Username=postgres;Password=comteck2020!@#;Database=Pole_samples_Product;Enlist=True;Timeout=0;Command Timeout=600;Pooling=false;MinPoolSize=20;MaxPoolSize=500;" + }, + "ServiceName": "Product", + "RabbitmqConfig": { + "HostAddress": "rabbitmq://192.168.0.248/", + "HostUserName": "comteck", + "HostPassword": "comteck3030" + }, + "MongoConfig": { + "Servers": [ + { + "Host": "192.168.0.248", + "Port": "27017" + } + ] + }, + "ReliableMessageOption": { + "NetworkInterfaceGatewayAddress": "192.168.0.1" + }, + "Kestrel": { + "EndpointDefaults": { + "Protocols": "Http2" + } + } } diff --git a/samples/proto/common/commonCommandResponse.proto b/samples/proto/common/commonCommandResponse.proto new file mode 100644 index 0000000..d9ff0c9 --- /dev/null +++ b/samples/proto/common/commonCommandResponse.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + + +package pole.Grpc.ExtraType; + +message CommonCommandResponse { + // 1 成功 2 失败 + int32 status = 1; + string message = 2; +} \ No newline at end of file diff --git a/samples/proto/service/Product/productType.proto b/samples/proto/service/Product/productType.proto index 1c9ddab..eccf85f 100644 --- a/samples/proto/service/Product/productType.proto +++ b/samples/proto/service/Product/productType.proto @@ -1,21 +1,17 @@ syntax = "proto3"; +import "common/commonCommandResponse.proto"; +package poleSample.apis.product; -package newArchitectureLab.apps.product; // The greeting service definition. service ProductType { // Sends a greeting - rpc GetById (GetProductTypeRequest) returns (GetProductTypeResponse); + rpc Add(AddProductTypeRequest) returns (pole.Grpc.ExtraType.CommonCommandResponse); } // The request message containing the user's name. -message GetProductTypeRequest { - string id = 1; -} - -// The response message containing the greetings. -message GetProductTypeResponse { +message AddProductTypeRequest { string id = 1; string name = 2; -} \ No newline at end of file +} diff --git a/src/Pole.Application/Cqrs/CommandResult.cs b/src/Pole.Application/Cqrs/CommandResult.cs index 50f4635..378ff74 100644 --- a/src/Pole.Application/Cqrs/CommandResult.cs +++ b/src/Pole.Application/Cqrs/CommandResult.cs @@ -4,18 +4,18 @@ using System.Text; namespace Pole.Application.Cqrs { - public class CommandResult - { - public CommandResult(int status,string message) - { - Status = status; - Message = message; - } - public static CommandResult SuccessResult = new CommandResult(1, "操作成功"); - /// - /// 1 Command Success 2 Command Faild ... - /// - public int Status { get;private set; } - public string Message { get;private set; } - } + //public class CommandResult + //{ + // public CommandResult(int status,string message) + // { + // Status = status; + // Message = message; + // } + // public static CommandResult SuccessResult = new CommandResult(1, "操作成功"); + // /// + // /// 1 Command Success 2 Command Faild ... + // /// + // public int Status { get;private set; } + // public string Message { get;private set; } + //} } diff --git a/src/Pole.Application/Cqrs/ICommand.cs b/src/Pole.Application/Cqrs/ICommand.cs new file mode 100644 index 0000000..c267214 --- /dev/null +++ b/src/Pole.Application/Cqrs/ICommand.cs @@ -0,0 +1,11 @@ +using MediatR; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Pole.Application.Cqrs +{ + public interface ICommand:IRequest + { + } +} diff --git a/src/Pole.Application/Cqrs/ICommandHandler.cs b/src/Pole.Application/Cqrs/ICommandHandler.cs index a67af1d..80aeb7f 100644 --- a/src/Pole.Application/Cqrs/ICommandHandler.cs +++ b/src/Pole.Application/Cqrs/ICommandHandler.cs @@ -5,7 +5,7 @@ using System.Text; namespace Pole.Application.Cqrs { - public interface ICommandHandler: IRequestHandler where TCommand : IRequest + public interface ICommandHandler: IRequestHandler where TCommand : ICommand { } } diff --git a/src/Pole.Application/Options.cs b/src/Pole.Application/PoleApplicationOptions.cs similarity index 75% rename from src/Pole.Application/Options.cs rename to src/Pole.Application/PoleApplicationOptions.cs index c36a780..f2ed52d 100644 --- a/src/Pole.Application/Options.cs +++ b/src/Pole.Application/PoleApplicationOptions.cs @@ -6,8 +6,13 @@ using System.Text; namespace Pole.Application { - public class Options + public class PoleApplicationOptions { + public PoleApplicationOptions(IServiceCollection services, params Assembly [] applicationAssemblies) + { + Services = services; + ApplicationAssemblies = applicationAssemblies; + } public IServiceCollection Services { get; set; } public IEnumerable ApplicationAssemblies { get; set; } diff --git a/src/Pole.Application/OptionsExtensions.cs b/src/Pole.Application/PoleApplicationOptionsExtensions.cs similarity index 60% rename from src/Pole.Application/OptionsExtensions.cs rename to src/Pole.Application/PoleApplicationOptionsExtensions.cs index 7e9c02b..1bc3c4d 100644 --- a/src/Pole.Application/OptionsExtensions.cs +++ b/src/Pole.Application/PoleApplicationOptionsExtensions.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.DependencyInjection; using Pole.Application.Cqrs; using Pole.Application.MediatR; +using Pole.Core.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; @@ -10,29 +11,22 @@ using System.Text; namespace Pole.Application { - public static class OptionsExtensions + public static class PoleApplicationOptionsExtensions { - public static Options AutoInjectionQueries(this Options options) + public static PoleApplicationOptions AutoInjectionDependency(this PoleApplicationOptions options) { var assemblies = options.ApplicationAssemblies; foreach (var assembly in assemblies) { - var queriesImplements = assembly.GetTypes().Where(m => typeof(IQueries).IsAssignableFrom(m) && m.IsClass && !m.IsAbstract); - foreach (var queriesImplement in queriesImplements) - { - var queriesService = queriesImplement.GetInterfaces().FirstOrDefault(); - options.Services.AddScoped(queriesService, queriesImplement); - } + AddScoped(options, assembly); + AddTransient(options, assembly); + AddSingleton(options, assembly); } return options; } - public static Options AddApplicationAssemblies(this Options options, params Assembly[] assemblies) - { - options.ApplicationAssemblies = assemblies.AsEnumerable(); - return options; - } - public static Options AutoInjectionCommandHandlersAndDomainEventHandlers(this Options options, ServiceLifetime lifetime = ServiceLifetime.Scoped) + + public static PoleApplicationOptions AutoInjectionCommandHandlersAndDomainEventHandlers(this PoleApplicationOptions options, ServiceLifetime lifetime = ServiceLifetime.Scoped) { options.Services.AddMediatR(config => { @@ -40,5 +34,36 @@ namespace Pole.Application }, options.ApplicationAssemblies.ToArray()); return options; } + + private static void AddScoped(PoleApplicationOptions options, Assembly assembly) + { + var queriesImplements = assembly.GetTypes().Where(m => typeof(IScopedDenpendency).IsAssignableFrom(m) && m.IsClass && !m.IsAbstract); + foreach (var queriesImplement in queriesImplements) + { + var queriesService = queriesImplement.GetInterfaces().FirstOrDefault(); + options.Services.AddScoped(queriesService, queriesImplement); + } + } + + private static void AddTransient(PoleApplicationOptions options, Assembly assembly) + { + var queriesImplements = assembly.GetTypes().Where(m => typeof(ITransientDependency).IsAssignableFrom(m) && m.IsClass && !m.IsAbstract); + foreach (var queriesImplement in queriesImplements) + { + var queriesService = queriesImplement.GetInterfaces().FirstOrDefault(); + options.Services.AddTransient(queriesService, queriesImplement); + } + } + + private static void AddSingleton(PoleApplicationOptions options, Assembly assembly) + { + var queriesImplements = assembly.GetTypes().Where(m => typeof(ISingleDependency).IsAssignableFrom(m) && m.IsClass && !m.IsAbstract); + foreach (var queriesImplement in queriesImplements) + { + var queriesService = queriesImplement.GetInterfaces().FirstOrDefault(); + options.Services.AddSingleton(queriesService, queriesImplement); + } + } + } } diff --git a/src/Pole.Application/ServiceCollectionExtensions.cs b/src/Pole.Application/ServiceCollectionExtensions.cs index 71e1c37..9cf4d66 100644 --- a/src/Pole.Application/ServiceCollectionExtensions.cs +++ b/src/Pole.Application/ServiceCollectionExtensions.cs @@ -1,18 +1,22 @@ -using Microsoft.Extensions.DependencyInjection; -using System; +using System; using System.Collections.Generic; using System.Text; using MediatR; using System.Reflection; using Pole.Application.Cqrs; using Pole.Application.Cqrs.Internal; +using Microsoft.Extensions.DependencyInjection; namespace Pole.Application { public static class ServiceCollectionExtensions { - public static IServiceCollection AddPoleApplication(this IServiceCollection services, Options options) + public static IServiceCollection AddPoleApplication(this IServiceCollection services, Action config, params Assembly[] assemblies) { + PoleApplicationOptions poleApplicationOptions = new PoleApplicationOptions(services, assemblies); + + config(poleApplicationOptions); + services.AddScoped(); return services; diff --git a/src/Pole.Domain/DomainHandleResult.cs b/src/Pole.Domain/DomainHandleResult.cs index 457f127..0118de3 100644 --- a/src/Pole.Domain/DomainHandleResult.cs +++ b/src/Pole.Domain/DomainHandleResult.cs @@ -1,4 +1,5 @@ -using System; +using Pole.Domain.UnitOfWork; +using System; using System.Collections.Generic; using System.Text; @@ -12,6 +13,10 @@ namespace Pole.Domain Message = message; } public static DomainHandleResult SuccessResult = new DomainHandleResult(1, "处理成功"); + public static implicit operator DomainHandleResult(CompleteResult completeResult) + { + return new DomainHandleResult(completeResult.Status, completeResult.Message); + } /// /// 1 Success 2 Faild ... /// diff --git a/src/Pole.Domain/IDomainEventHandler.cs b/src/Pole.Domain/IDomainEventHandler.cs index 066fd5f..18b32e3 100644 --- a/src/Pole.Domain/IDomainEventHandler.cs +++ b/src/Pole.Domain/IDomainEventHandler.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; namespace Pole.Domain { - public interface IDomainEventHandler : IRequestHandler where TCommand : IRequest + public interface IDomainEventHandler : IRequestHandler where TCommand : IRequest { } diff --git a/src/Pole.Domain/IRepository.cs b/src/Pole.Domain/IRepository.cs index 5b7ae93..6350c50 100644 --- a/src/Pole.Domain/IRepository.cs +++ b/src/Pole.Domain/IRepository.cs @@ -1,4 +1,5 @@ -using Pole.Domain.UnitOfWork; +using Pole.Core.DependencyInjection; +using Pole.Domain.UnitOfWork; using System; using System.Collections.Generic; using System.Text; @@ -11,11 +12,11 @@ namespace Pole.Domain { void Update(T entity); void Delete(T entity); - Task Add(T entity); + void Add(T entity); Task Get(string id); IUnitOfWork UnitOfWork { get; } } - public interface IRepository + public interface IRepository: IScopedDenpendency { } diff --git a/src/Pole.Domain/ServiceCollectionExtensions.cs b/src/Pole.Domain/ServiceCollectionExtensions.cs index 0f3bca3..8bd95c5 100644 --- a/src/Pole.Domain/ServiceCollectionExtensions.cs +++ b/src/Pole.Domain/ServiceCollectionExtensions.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Text; -namespace Microsoft.Extensions.DependencyInjection +namespace Pole.Domain { public static class ServiceCollectionExtensions { diff --git a/src/Pole.Grpc/ExtraType/CommonCommandResponse.cs b/src/Pole.Grpc/ExtraType/CommonCommandResponse.cs new file mode 100644 index 0000000..ffdd9b6 --- /dev/null +++ b/src/Pole.Grpc/ExtraType/CommonCommandResponse.cs @@ -0,0 +1,17 @@ +using Pole.Application.Cqrs; +using Pole.Domain; +using Pole.Domain.UnitOfWork; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Pole.Grpc.ExtraType +{ + public partial class CommonCommandResponse + { + public static implicit operator CommonCommandResponse(CompleteResult domainHandleResult) + { + return new CompleteResult(domainHandleResult.Status, domainHandleResult.Message); + } + } +} diff --git a/src/Pole.Grpc/ExtraType/Protos/commonCommandResponse.proto b/src/Pole.Grpc/ExtraType/Protos/commonCommandResponse.proto new file mode 100644 index 0000000..d9ff0c9 --- /dev/null +++ b/src/Pole.Grpc/ExtraType/Protos/commonCommandResponse.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + + +package pole.Grpc.ExtraType; + +message CommonCommandResponse { + // 1 成功 2 失败 + int32 status = 1; + string message = 2; +} \ No newline at end of file diff --git a/src/Pole.Grpc/Pole.Grpc.csproj b/src/Pole.Grpc/Pole.Grpc.csproj index 7de0efe..8678271 100644 --- a/src/Pole.Grpc/Pole.Grpc.csproj +++ b/src/Pole.Grpc/Pole.Grpc.csproj @@ -11,4 +11,9 @@ + + + + + diff --git a/src/Pole.Grpc/PoleGrpcOption.cs b/src/Pole.Grpc/PoleGrpcOption.cs new file mode 100644 index 0000000..4128ed8 --- /dev/null +++ b/src/Pole.Grpc/PoleGrpcOption.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; + +namespace Pole.Grpc +{ + public class PoleGrpcOptions + { + public PoleGrpcOptions(IServiceCollection services,params Assembly [] assemblies) + { + Services = services; + ApplicationAssemblies = assemblies.ToList(); + AutoInject = true; + } + public IServiceCollection Services { get;private set; } + public IEnumerable ApplicationAssemblies { get; set; } + public bool AutoInject { get; set; } + } +} diff --git a/src/Pole.Grpc/PoleGrpcOptionExtensions.cs b/src/Pole.Grpc/PoleGrpcOptionExtensions.cs new file mode 100644 index 0000000..29b144f --- /dev/null +++ b/src/Pole.Grpc/PoleGrpcOptionExtensions.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Pole.Application; +using Pole.Domain; + +namespace Pole.Grpc +{ + public static class PoleGrpcOptionExtensions + { + public static PoleGrpcOptions AddPoleApplication(this PoleGrpcOptions poleGrpcOptions) + { + poleGrpcOptions.Services.AddPoleApplication(options => { + options.AutoInjectionCommandHandlersAndDomainEventHandlers(); + if (poleGrpcOptions.AutoInject) + { + options.AutoInjectionDependency(); + } + }, poleGrpcOptions.ApplicationAssemblies.ToArray()); + + return poleGrpcOptions; + } + public static PoleGrpcOptions AddPoleDomain(this PoleGrpcOptions poleGrpcOptions) + { + poleGrpcOptions.Services.AddPoleDomain(); + return poleGrpcOptions; + } + } +} diff --git a/src/Pole.Grpc/ServiceCollectionExtensions.cs b/src/Pole.Grpc/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..d44ed4f --- /dev/null +++ b/src/Pole.Grpc/ServiceCollectionExtensions.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.DependencyInjection; +using Pole.Grpc; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; + +namespace Microsoft.Extensions.DependencyInjection +{ + public static class ServiceCollectionExtensions + { + public static IServiceCollection AddPoleGrpc(this IServiceCollection services, params Assembly[] assemblies) + { + PoleGrpcOptions poleGrpcOptions = new PoleGrpcOptions(services, assemblies); + poleGrpcOptions.AddPoleApplication(); + poleGrpcOptions.AddPoleDomain(); + // poleGrpcOptions.Services.AddGrpcValidation(); + return services; + } + } +} diff --git a/src/Pole.Grpc/Validation/ServiceCollectionExtensions.cs b/src/Pole.Grpc/Validation/ServiceCollectionExtensions.cs index da3f54f..6f6e0b8 100644 --- a/src/Pole.Grpc/Validation/ServiceCollectionExtensions.cs +++ b/src/Pole.Grpc/Validation/ServiceCollectionExtensions.cs @@ -11,7 +11,7 @@ using System.Text; namespace Microsoft.Extensions.DependencyInjection { - public static class ServiceCollectionExtensions + public static class ServiceCollectionValidationExtensions { public static IServiceCollection AddGrpcValidation(this IServiceCollection services) { diff --git a/src/Pole.ReliableMessage/BackgroundServiceBasedProcessorServer.cs b/src/Pole.ReliableMessage/BackgroundServiceBasedProcessorServer.cs index e1b3fb8..d6d8c73 100644 --- a/src/Pole.ReliableMessage/BackgroundServiceBasedProcessorServer.cs +++ b/src/Pole.ReliableMessage/BackgroundServiceBasedProcessorServer.cs @@ -43,11 +43,5 @@ namespace Pole.ReliableMessage { return Start(stoppingToken); } - public override void Dispose() - { - // 等待 10秒 待 消息处理完 - _compositeTask?.Wait((int)TimeSpan.FromSeconds(10).TotalMilliseconds); - base.Dispose(); - } } } diff --git a/src/Pole.ReliableMessage/ComteckReliableMessageServiceCollectionExtensions.cs b/src/Pole.ReliableMessage/PoleReliableMessageServiceCollectionExtensions.cs similarity index 95% rename from src/Pole.ReliableMessage/ComteckReliableMessageServiceCollectionExtensions.cs rename to src/Pole.ReliableMessage/PoleReliableMessageServiceCollectionExtensions.cs index a10f5d7..3dcc225 100644 --- a/src/Pole.ReliableMessage/ComteckReliableMessageServiceCollectionExtensions.cs +++ b/src/Pole.ReliableMessage/PoleReliableMessageServiceCollectionExtensions.cs @@ -14,9 +14,9 @@ using System.Text; namespace Microsoft.Extensions.DependencyInjection { - public static class ComteckReliableMessageServiceCollectionExtensions + public static class PoleReliableMessageServiceCollectionExtensions { - public static IServiceCollection AddComteckReliableMessage(this IServiceCollection services, Action optionConfig) + public static IServiceCollection AddPoleReliableMessage(this IServiceCollection services, Action optionConfig) { ReliableMessageOption reliableMessageOption = new ReliableMessageOption(); optionConfig(reliableMessageOption);