├── .editorconfig ├── .gitattributes ├── .github └── workflows │ └── publish.yaml ├── .gitignore ├── license.md ├── readme.md └── source ├── AspNetCore ├── Attributes │ └── EnumAuthorizeAttribute.cs ├── DotNetCore.AspNetCore.csproj ├── Extensions │ ├── ApplicationBuilderExtensions.cs │ ├── BinaryFileExtensions.cs │ ├── HttpRequestExtensions.cs │ ├── JsonStringBoolConverter.cs │ ├── ResultExtensions.cs │ └── ServiceCollectionExtensions.cs └── readme.md ├── Directory.Build.props ├── Directory.Packages.props ├── Domain ├── DotNetCore.Domain.csproj ├── Entity.cs ├── Event.cs └── readme.md ├── DotNetCore.slnx ├── EntityFrameworkCore ├── DotNetCore.EntityFrameworkCore.csproj ├── Extensions.cs ├── Repository │ ├── EFCommandRepository.cs │ ├── EFQueryRepository.cs │ └── EFRepository.cs ├── UnitOfWork │ ├── IUnitOfWork.cs │ └── UnitOfWork.cs └── readme.md ├── Extensions ├── AssemblyExtensions.cs ├── ByteExtensions.cs ├── ClaimsPrincipalExtensions.cs ├── DateTimeExtensions.cs ├── DirectoryInfoExtensions.cs ├── DotNetCore.Extensions.csproj ├── EnumExtensions.cs ├── ObjectExtensions.cs ├── QueryableExtensions.cs ├── StreamExtensions.cs ├── StringExtensions.cs └── readme.md ├── IoC ├── DotNetCore.IoC.csproj ├── Extensions.cs └── readme.md ├── Logging ├── DotNetCore.Logging.csproj ├── Extensions.cs └── readme.md ├── Mapping ├── DotNetCore.Mapping.csproj ├── Extensions.cs └── readme.md ├── Mediator ├── DotNetCore.Mediator.csproj ├── Extensions.cs ├── IHandler.cs ├── IMediator.cs ├── Mediator.cs └── readme.md ├── MongoDB ├── Context │ ├── IMongoContext.cs │ └── MongoContext.cs ├── Document │ ├── Document.cs │ └── IDocument.cs ├── DotNetCore.MongoDB.csproj ├── Filters.cs ├── Repository │ ├── MongoCommandRepository.cs │ ├── MongoQueryRepository.cs │ └── MongoRepository.cs └── readme.md ├── Objects ├── DotNetCore.Objects.csproj ├── File │ ├── BinaryFile.cs │ └── BinaryFileExtensions.cs ├── Grid │ ├── Filter.cs │ ├── Filters.cs │ ├── Grid.cs │ ├── GridExtensions.cs │ ├── GridParameters.cs │ ├── Order.cs │ └── Page.cs └── readme.md ├── RabbitMQ ├── Connection.cs ├── DotNetCore.RabbitMQ.csproj ├── IQueue.cs ├── Queue.cs └── readme.md ├── Repositories ├── DotNetCore.Repositories.csproj ├── ICommandRepository.cs ├── IQueryRepository.cs ├── IRepository.cs ├── Repository.cs └── readme.md ├── Results ├── DotNetCore.Results.csproj ├── Result.cs └── readme.md ├── Security ├── Cryptography │ ├── CryptographyService.cs │ └── ICryptographyService.cs ├── DotNetCore.Security.csproj ├── Extensions.cs ├── Hash │ ├── HashService.cs │ └── IHashService.cs ├── KeyGenerator.cs └── readme.md ├── Services ├── Csv │ ├── CsvService.cs │ └── ICsvService.cs ├── DotNetCore.Services.csproj ├── Extensions.cs ├── FileCache │ ├── FileCache.cs │ ├── FileCacheContent.cs │ └── IFileCache.cs ├── Http │ ├── HttpOptions.cs │ ├── HttpService.cs │ └── IHttpService.cs ├── JsonStringLocalizer.cs └── readme.md ├── Validation ├── DotNetCore.Validation.csproj ├── Extensions.cs └── readme.md └── global.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_size = 4 6 | indent_style = space 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.cs diff=csharp 3 | -------------------------------------------------------------------------------- /.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | name: publish 2 | on: 3 | push: 4 | branches: [main] 5 | jobs: 6 | publish: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v4 11 | 12 | - name: DotNet Setup 13 | uses: actions/setup-dotnet@v4 14 | with: 15 | dotnet-version: "9.x.x" 16 | env: 17 | NUGET_PACKAGES: ${{ runner.temp }}/nuget/packages 18 | 19 | - name: DotNet Pack 20 | run: find ./source -name '*.csproj' -exec dotnet pack {} --configuration Release --output packages \; 21 | 22 | - name: DotNet NuGet Delete 23 | run: curl -s https://azuresearch-usnc.nuget.org/query?q=owner:rafaelfgx | jq -r '.data[] | "dotnet nuget delete \(.id) \(.version) --non-interactive --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }}"' | xargs -I {} bash -c "{}" 24 | 25 | - name: DotNet NuGet Push 26 | run: dotnet nuget push "packages/*.nupkg" --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }} --skip-duplicate --no-symbols 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.bat 2 | *.dll 3 | *.exe 4 | *.lib 5 | *.log 6 | *.pdb 7 | *.ps1 8 | *.suo 9 | *.tmp 10 | *.user 11 | *.userprefs 12 | *.vspx 13 | .vs 14 | [Bb]in 15 | [Dd]ebug 16 | [Ll]og 17 | [Oo]bj 18 | [Rr]elease 19 | [Rr]eleases 20 | [Tt]est[Rr]esults 21 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 2 | 3 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 4 | 5 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 6 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore 2 | 3 | ![](https://github.com/rafaelfgx/DotNetCore/actions/workflows/publish.yaml/badge.svg) 4 | 5 | .NET Nuget Packages. 6 | 7 | https://www.nuget.org/profiles/rafaelfgx 8 | 9 | ## Documentation 10 | 11 | [AspNetCore](https://github.com/rafaelfgx/DotNetCore/tree/main/source/AspNetCore) 12 | 13 | [Domain](https://github.com/rafaelfgx/DotNetCore/tree/main/source/Domain) 14 | 15 | [EntityFrameworkCore](https://github.com/rafaelfgx/DotNetCore/tree/main/source/EntityFrameworkCore) 16 | 17 | [Extensions](https://github.com/rafaelfgx/DotNetCore/tree/main/source/Extensions) 18 | 19 | [IoC](https://github.com/rafaelfgx/DotNetCore/tree/main/source/IoC) 20 | 21 | [Logging](https://github.com/rafaelfgx/DotNetCore/tree/main/source/Logging) 22 | 23 | [Mapping](https://github.com/rafaelfgx/DotNetCore/tree/main/source/Mapping) 24 | 25 | [Mediator](https://github.com/rafaelfgx/DotNetCore/tree/main/source/Mediator) 26 | 27 | [MongoDB](https://github.com/rafaelfgx/DotNetCore/tree/main/source/MongoDB) 28 | 29 | [Objects](https://github.com/rafaelfgx/DotNetCore/tree/main/source/Objects) 30 | 31 | [RabbitMQ](https://github.com/rafaelfgx/DotNetCore/tree/main/source/RabbitMQ) 32 | 33 | [Repositories](https://github.com/rafaelfgx/DotNetCore/tree/main/source/Repositories) 34 | 35 | [Results](https://github.com/rafaelfgx/DotNetCore/tree/main/source/Results) 36 | 37 | [Security](https://github.com/rafaelfgx/DotNetCore/tree/main/source/Security) 38 | 39 | [Services](https://github.com/rafaelfgx/DotNetCore/tree/main/source/Services) 40 | 41 | [Validation](https://github.com/rafaelfgx/DotNetCore/tree/main/source/Validation) 42 | -------------------------------------------------------------------------------- /source/AspNetCore/Attributes/EnumAuthorizeAttribute.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | 3 | namespace DotNetCore.AspNetCore; 4 | 5 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] 6 | public sealed class EnumAuthorizeAttribute : AuthorizeAttribute 7 | { 8 | public EnumAuthorizeAttribute(params object[] roles) => Roles = string.Join(",", roles.Select(role => Enum.GetName(role.GetType(), role))); 9 | } 10 | -------------------------------------------------------------------------------- /source/AspNetCore/DotNetCore.AspNetCore.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.AspNetCore 4 | DotNetCore.AspNetCore 5 | DotNetCore.AspNetCore 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/AspNetCore 7 | AspNetCore, Attribute, Attributes, IApplicationBuilder, ApplicationBuilder, IHostBuilder, HostBuilder, HttpRequest, IServiceCollection, ServiceCollection, Result, Results, IActionResult, ActionResult 8 | DotNetCore.AspNetCore 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /source/AspNetCore/Extensions/ApplicationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.Hosting; 5 | 6 | namespace DotNetCore.AspNetCore; 7 | 8 | public static class ApplicationBuilderExtensions 9 | { 10 | public static void UseCorsAllowAny(this IApplicationBuilder application) => application.UseCors("AllowAny"); 11 | 12 | public static void UseException(this IApplicationBuilder application) 13 | { 14 | var environment = application.ApplicationServices.GetRequiredService(); 15 | 16 | if (environment.IsDevelopment()) application.UseDeveloperExceptionPage(); 17 | } 18 | 19 | public static void UseLocalization(this IApplicationBuilder application, params string[] cultures) => application.UseRequestLocalization(options => options.AddSupportedCultures(cultures).AddSupportedUICultures(cultures).SetDefaultCulture(cultures.First())); 20 | } 21 | -------------------------------------------------------------------------------- /source/AspNetCore/Extensions/BinaryFileExtensions.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Objects; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.StaticFiles; 4 | 5 | namespace DotNetCore.AspNetCore; 6 | 7 | public static class BinaryFileExtensions 8 | { 9 | public static IActionResult FileResult(this Task binaryFile) 10 | { 11 | if (binaryFile is null) return new NotFoundResult(); 12 | 13 | var file = binaryFile.Result; 14 | 15 | if (file is null) return new NotFoundResult(); 16 | 17 | new FileExtensionContentTypeProvider().TryGetContentType(file.ContentType, out var contentType); 18 | 19 | return contentType is null ? new NotFoundResult() : new FileContentResult(file.Bytes, contentType) { FileDownloadName = file.Name }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/AspNetCore/Extensions/HttpRequestExtensions.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Objects; 2 | using Microsoft.AspNetCore.Http; 3 | 4 | namespace DotNetCore.AspNetCore; 5 | 6 | public static class HttpRequestExtensions 7 | { 8 | public static IList Files(this HttpRequest request) 9 | { 10 | var files = new List(); 11 | 12 | foreach (var file in request.Form.Files) 13 | { 14 | using var memoryStream = new MemoryStream(); 15 | 16 | file.CopyTo(memoryStream); 17 | 18 | files.Add(new BinaryFile(Guid.NewGuid(), file.Name, memoryStream.ToArray(), file.Length, file.ContentType)); 19 | } 20 | 21 | return files; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /source/AspNetCore/Extensions/JsonStringBoolConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace DotNetCore.AspNetCore; 5 | 6 | public class JsonStringBoolConverter : JsonConverter 7 | { 8 | public override bool Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => bool.TryParse(reader.GetString(), out var result) && result; 9 | 10 | public override void Write(Utf8JsonWriter writer, bool value, JsonSerializerOptions options) => writer.WriteBooleanValue(value); 11 | } 12 | -------------------------------------------------------------------------------- /source/AspNetCore/Extensions/ResultExtensions.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Results; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace DotNetCore.AspNetCore; 5 | 6 | public static class ResultExtensions 7 | { 8 | public static IActionResult ApiResult(this Result result) => new ObjectResult(result.HasMessage ? result.Message : result.Value) { StatusCode = (int)result.Status }; 9 | 10 | public static IActionResult ApiResult(this Task> result) => ApiResult(result.Result); 11 | 12 | public static IActionResult ApiResult(this Result result) => new ObjectResult(result.Message) { StatusCode = (int)result.Status }; 13 | 14 | public static IActionResult ApiResult(this Task result) => ApiResult(result.Result); 15 | 16 | public static IActionResult ApiResult(this T result) => new ObjectResult(result); 17 | 18 | public static IActionResult ApiResult(this Task result) => ApiResult(result.Result); 19 | } 20 | -------------------------------------------------------------------------------- /source/AspNetCore/Extensions/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authentication.JwtBearer; 2 | using Microsoft.AspNetCore.Authorization; 3 | using Microsoft.AspNetCore.Http.Features; 4 | using Microsoft.AspNetCore.Mvc.Authorization; 5 | using Microsoft.AspNetCore.StaticFiles; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.OpenApi.Models; 8 | using Swashbuckle.AspNetCore.SwaggerGen; 9 | using System.Text.Json.Serialization; 10 | 11 | namespace DotNetCore.AspNetCore; 12 | 13 | public static class ServiceCollectionExtensions 14 | { 15 | public static IMvcBuilder AddAuthorizationPolicy(this IMvcBuilder builder) => builder.AddMvcOptions(options => options.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()))); 16 | 17 | public static IServiceCollection AddCorsAllowAny(this IServiceCollection services) => services.AddCors(options => options.AddPolicy("AllowAny", policy => policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod())); 18 | 19 | public static IServiceCollection AddFileExtensionContentTypeProvider(this IServiceCollection services) => services.AddSingleton(); 20 | 21 | public static IMvcBuilder AddJsonOptions(this IMvcBuilder builder) => builder.AddJsonOptions(options => 22 | { 23 | options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; 24 | options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); 25 | options.JsonSerializerOptions.Converters.Add(new JsonStringBoolConverter()); 26 | }); 27 | 28 | public static void AddSwaggerDefault(this IServiceCollection services) => services.AddSwaggerGen(ConfigureSwaggerGenOptions); 29 | 30 | public static IServiceCollection ConfigureFormOptionsMaxLengthLimit(this IServiceCollection services) => services.Configure(options => 31 | { 32 | options.ValueLengthLimit = int.MaxValue; 33 | options.MultipartBodyLengthLimit = int.MaxValue; 34 | }); 35 | 36 | private static void ConfigureSwaggerGenOptions(this SwaggerGenOptions options) 37 | { 38 | options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme 39 | { 40 | Type = SecuritySchemeType.ApiKey, 41 | In = ParameterLocation.Header, 42 | Name = "Authorization" 43 | }); 44 | 45 | options.AddSecurityRequirement(new OpenApiSecurityRequirement 46 | { 47 | { 48 | new OpenApiSecurityScheme 49 | { 50 | Reference = new OpenApiReference 51 | { 52 | Type = ReferenceType.SecurityScheme, 53 | Id = JwtBearerDefaults.AuthenticationScheme 54 | }, 55 | In = ParameterLocation.Header, 56 | Scheme = SecuritySchemeType.OAuth2.ToString(), 57 | Name = JwtBearerDefaults.AuthenticationScheme 58 | }, 59 | new List() 60 | } 61 | }); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /source/AspNetCore/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.AspNetCore 2 | 3 | ## Attributes 4 | 5 | ### EnumAuthorizeAttribute 6 | 7 | ```cs 8 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] 9 | public sealed class EnumAuthorizeAttribute : AuthorizeAttribute 10 | { 11 | public EnumAuthorizeAttribute(params object[] roles) { } 12 | } 13 | ``` 14 | 15 | ## Extensions 16 | 17 | ### ApplicationBuilderExtensions 18 | 19 | ```cs 20 | public static class ApplicationBuilderExtensions 21 | { 22 | public static void UseCorsAllowAny(this IApplicationBuilder application) { } 23 | 24 | public static void UseException(this IApplicationBuilder application) { } 25 | 26 | public static void UseLocalization(this IApplicationBuilder application, params string[] cultures) { } 27 | 28 | public static void ConfigureFormOptions(this IServiceCollection services) { } 29 | } 30 | ``` 31 | 32 | ### BinaryFileExtensions 33 | 34 | ```cs 35 | public static class BinaryFileExtensions 36 | { 37 | public static IActionResult FileResult(this Task binaryFile) { } 38 | } 39 | ``` 40 | 41 | ### HttpRequestExtensions 42 | 43 | ```cs 44 | public static class HttpRequestExtensions 45 | { 46 | public static IList Files(this HttpRequest request) { } 47 | } 48 | ``` 49 | 50 | ### ResultExtensions 51 | 52 | ```cs 53 | public static class ResultExtensions 54 | { 55 | public static IActionResult ApiResult(this Result result) { } 56 | 57 | public static IActionResult ApiResult(this Task> result) { } 58 | 59 | public static IActionResult ApiResult(this Result result) { } 60 | 61 | public static IActionResult ApiResult(this Task result) { } 62 | 63 | public static IActionResult ApiResult(this T result) { } 64 | 65 | public static IActionResult ApiResult(this Task result) { } 66 | } 67 | ``` 68 | 69 | ### ServiceCollectionExtensions 70 | 71 | ```cs 72 | public static class ServiceCollectionExtensions 73 | { 74 | public static IMvcBuilder AddAuthorizationPolicy(this IMvcBuilder builder) { } 75 | 76 | public static IServiceCollection AddCorsAllowAny(this IServiceCollection services) { } 77 | 78 | public static IServiceCollection AddFileExtensionContentTypeProvider(this IServiceCollection services) { } 79 | 80 | public static IMvcBuilder AddJsonOptions(this IMvcBuilder builder) { } 81 | 82 | public static void AddSwaggerDefault(this IServiceCollection services) { } 83 | 84 | public static IServiceCollection ConfigureFormOptionsMaxLengthLimit(this IServiceCollection services) { } 85 | } 86 | ``` 87 | -------------------------------------------------------------------------------- /source/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | true 5 | true 6 | false 7 | enable 8 | true 9 | latest 10 | en 11 | MIT 12 | readme.md 13 | true 14 | git 15 | https://github.com/rafaelfgx/DotNetCore 16 | snupkg 17 | net9.0 18 | 19.17.0 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /source/Directory.Packages.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | false 5 | true 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /source/Domain/DotNetCore.Domain.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.Domain 4 | DotNetCore.Domain 5 | DotNetCore.Domain 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/Domain 7 | Domain, DDD, DomainDrivenDesign, Entity, Event, ValueObject 8 | DotNetCore.Domain 9 | 10 | 11 | -------------------------------------------------------------------------------- /source/Domain/Entity.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Domain; 2 | 3 | public abstract class Entity 4 | { 5 | public long Id { get; init; } 6 | 7 | public static bool operator !=(Entity left, Entity right) => !(left == right); 8 | 9 | public static bool operator ==(Entity left, Entity right) => left?.Equals(right) == true; 10 | 11 | public override bool Equals(object obj) => obj is Entity entity && (ReferenceEquals(this, entity) || Id == entity.Id); 12 | 13 | public override int GetHashCode() => Id.GetHashCode(); 14 | } 15 | -------------------------------------------------------------------------------- /source/Domain/Event.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Domain; 2 | 3 | public abstract class Event 4 | { 5 | public Guid Id { get; } = Guid.NewGuid(); 6 | 7 | public DateTime DateTime { get; } = DateTime.UtcNow; 8 | } 9 | -------------------------------------------------------------------------------- /source/Domain/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.Domain 2 | 3 | ## Entity 4 | 5 | ```cs 6 | public abstract class Entity 7 | { 8 | public long Id { get; init; } 9 | 10 | public static bool operator !=(Entity left, Entity right) { } 11 | 12 | public static bool operator ==(Entity left, Entity right) { } 13 | 14 | public override bool Equals(object obj) { } 15 | 16 | public override int GetHashCode() { } 17 | } 18 | ``` 19 | 20 | ## Event 21 | 22 | ```cs 23 | public abstract class Event 24 | { 25 | public Guid Id { get; } = Guid.NewGuid(); 26 | 27 | public DateTime DateTime { get; } = DateTime.UtcNow; 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /source/DotNetCore.slnx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /source/EntityFrameworkCore/DotNetCore.EntityFrameworkCore.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.EntityFrameworkCore 4 | DotNetCore.EntityFrameworkCore 5 | DotNetCore.EntityFrameworkCore 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/EntityFrameworkCore 7 | ORM, ObjectRelationalMapping, EntityFramework, EntityFrameworkCore, Context, Repository, GenericRepository, BaseRepository, RepositoryBase, CommandRepository, QueryRepository, CQRS, Command, Query 8 | DotNetCore.EntityFrameworkCore 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /source/EntityFrameworkCore/Extensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace DotNetCore.EntityFrameworkCore; 5 | 6 | public static class Extensions 7 | { 8 | public static void AddContext(this IServiceCollection services, Action options) where T : DbContext 9 | { 10 | services.AddDbContextPool(options); 11 | 12 | services.BuildServiceProvider().GetRequiredService().Database.Migrate(); 13 | 14 | services.AddScoped>(); 15 | } 16 | 17 | public static void AddContextMemory(this IServiceCollection services) where T : DbContext 18 | { 19 | services.AddDbContextPool(options => options.UseInMemoryDatabase(typeof(T).Name)); 20 | 21 | services.BuildServiceProvider().GetRequiredService().Database.EnsureCreated(); 22 | 23 | services.AddScoped>(); 24 | } 25 | 26 | public static DbSet CommandSet(this DbContext context) where T : class => context.DetectChangesLazyLoading(true).Set(); 27 | 28 | public static DbContext DetectChangesLazyLoading(this DbContext context, bool enabled) 29 | { 30 | context.ChangeTracker.AutoDetectChangesEnabled = enabled; 31 | context.ChangeTracker.LazyLoadingEnabled = enabled; 32 | context.ChangeTracker.QueryTrackingBehavior = enabled ? QueryTrackingBehavior.TrackAll : QueryTrackingBehavior.NoTracking; 33 | 34 | return context; 35 | } 36 | 37 | public static IQueryable QuerySet(this DbContext context) where T : class => context.DetectChangesLazyLoading(false).Set().AsNoTracking(); 38 | 39 | public static object[] PrimaryKeyValues(this DbContext context, object entity) => context.Model.FindEntityType(typeof(T))?.FindPrimaryKey()?.Properties.Select(property => entity.GetType().GetProperty(property.Name)?.GetValue(entity, default)).ToArray(); 40 | } 41 | -------------------------------------------------------------------------------- /source/EntityFrameworkCore/Repository/EFCommandRepository.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Repositories; 2 | using Microsoft.EntityFrameworkCore; 3 | using System.Linq.Expressions; 4 | 5 | namespace DotNetCore.EntityFrameworkCore; 6 | 7 | public class EFCommandRepository(DbContext context) : ICommandRepository where T : class 8 | { 9 | private DbSet Set => context.CommandSet(); 10 | 11 | public void Add(T item) => Set.Add(item); 12 | 13 | public Task AddAsync(T item) => Set.AddAsync(item).AsTask(); 14 | 15 | public void AddRange(IEnumerable items) => Set.AddRange(items); 16 | 17 | public Task AddRangeAsync(IEnumerable items) => Set.AddRangeAsync(items); 18 | 19 | public void Delete(object key) 20 | { 21 | var item = Set.Find(key); 22 | 23 | if (item is null) return; 24 | 25 | Set.Remove(item); 26 | } 27 | 28 | public void Delete(Expression> where) 29 | { 30 | var items = Set.Where(where); 31 | 32 | if (!items.Any()) return; 33 | 34 | Set.RemoveRange(items); 35 | } 36 | 37 | public Task DeleteAsync(object key) => Task.Run(() => Delete(key)); 38 | 39 | public Task DeleteAsync(Expression> where) => Task.Run(() => Delete(where)); 40 | 41 | public void Update(T item) 42 | { 43 | var primaryKeyValues = context.PrimaryKeyValues(item); 44 | 45 | var entity = Set.Find(primaryKeyValues); 46 | 47 | if (entity is null) return; 48 | 49 | context.Entry(entity).State = EntityState.Detached; 50 | 51 | context.Update(item); 52 | } 53 | 54 | public Task UpdateAsync(T item) => Task.Run(() => Update(item)); 55 | 56 | public void UpdatePartial(object item) 57 | { 58 | var primaryKeyValues = context.PrimaryKeyValues(item); 59 | 60 | var entity = Set.Find(primaryKeyValues); 61 | 62 | if (entity is null) return; 63 | 64 | var entry = context.Entry(entity); 65 | 66 | entry.CurrentValues.SetValues(item); 67 | 68 | foreach (var navigation in entry.Metadata.GetNavigations()) 69 | { 70 | if (navigation.IsOnDependent || navigation.IsCollection || !navigation.ForeignKey.IsOwnership) continue; 71 | 72 | var property = item.GetType().GetProperty(navigation.Name); 73 | 74 | if (property is null) continue; 75 | 76 | var value = property.GetValue(item, default); 77 | 78 | entry.Reference(navigation.Name).TargetEntry?.CurrentValues.SetValues(value!); 79 | } 80 | } 81 | 82 | public Task UpdatePartialAsync(object item) => Task.Run(() => UpdatePartial(item)); 83 | 84 | public void UpdateRange(IEnumerable items) => Set.UpdateRange(items); 85 | 86 | public Task UpdateRangeAsync(IEnumerable items) => Task.Run(() => UpdateRange(items)); 87 | } 88 | -------------------------------------------------------------------------------- /source/EntityFrameworkCore/Repository/EFQueryRepository.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Repositories; 2 | using Microsoft.EntityFrameworkCore; 3 | using System.Linq.Expressions; 4 | 5 | namespace DotNetCore.EntityFrameworkCore; 6 | 7 | public class EFQueryRepository(DbContext context) : IQueryRepository where T : class 8 | { 9 | public IQueryable Queryable => context.QuerySet(); 10 | 11 | public bool Any() => Queryable.Any(); 12 | 13 | public bool Any(Expression> where) => Queryable.Any(where); 14 | 15 | public Task AnyAsync() => Queryable.AnyAsync(); 16 | 17 | public Task AnyAsync(Expression> where) => Queryable.AnyAsync(where); 18 | 19 | public long Count() => Queryable.LongCount(); 20 | 21 | public long Count(Expression> where) => Queryable.LongCount(where); 22 | 23 | public Task CountAsync() => Queryable.LongCountAsync(); 24 | 25 | public Task CountAsync(Expression> where) => Queryable.LongCountAsync(where); 26 | 27 | public T Get(object key) => context.DetectChangesLazyLoading(false).Set().Find(key); 28 | 29 | public Task GetAsync(object key) => context.DetectChangesLazyLoading(false).Set().FindAsync(key).AsTask(); 30 | 31 | public IEnumerable List() => Queryable.ToList(); 32 | 33 | public async Task> ListAsync() => await Queryable.ToListAsync().ConfigureAwait(false); 34 | } 35 | -------------------------------------------------------------------------------- /source/EntityFrameworkCore/Repository/EFRepository.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Repositories; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace DotNetCore.EntityFrameworkCore; 5 | 6 | public class EFRepository(DbContext context) : Repository(new EFCommandRepository(context), new EFQueryRepository(context)) where T : class; 7 | -------------------------------------------------------------------------------- /source/EntityFrameworkCore/UnitOfWork/IUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.EntityFrameworkCore; 2 | 3 | public interface IUnitOfWork 4 | { 5 | Task SaveChangesAsync(); 6 | } 7 | -------------------------------------------------------------------------------- /source/EntityFrameworkCore/UnitOfWork/UnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | 3 | namespace DotNetCore.EntityFrameworkCore; 4 | 5 | public sealed class UnitOfWork(TDbContext context) : IUnitOfWork where TDbContext : DbContext 6 | { 7 | public Task SaveChangesAsync() => context.SaveChangesAsync(); 8 | } 9 | -------------------------------------------------------------------------------- /source/EntityFrameworkCore/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.EntityFrameworkCore 2 | 3 | ## Extensions 4 | 5 | ```cs 6 | public static class Extensions 7 | { 8 | public static void AddContext(this IServiceCollection services, Action options) where T : DbContext { } 9 | 10 | public static void AddContextMemory(this IServiceCollection services) where T : DbContext { } 11 | 12 | public static DbSet CommandSet(this DbContext context) where T : class { } 13 | 14 | public static DbContext DetectChangesLazyLoading(this DbContext context, bool enabled) { } 15 | 16 | public static IQueryable QuerySet(this DbContext context) where T : class { } 17 | } 18 | ``` 19 | 20 | ### EFCommandRepository 21 | 22 | ```cs 23 | public class EFCommandRepository : ICommandRepository where T : class 24 | { 25 | public EFCommandRepository(DbContext context) { } 26 | 27 | public void Add(T item) { } 28 | 29 | public Task AddAsync(T item) { } 30 | 31 | public void AddRange(IEnumerable items) { } 32 | 33 | public Task AddRangeAsync(IEnumerable items) { } 34 | 35 | public void Delete(object key) { } 36 | 37 | public void Delete(Expression> where) { } 38 | 39 | public Task DeleteAsync(object key) { } 40 | 41 | public Task DeleteAsync(Expression> where) { } 42 | 43 | public void Update(T item) { } 44 | 45 | public Task UpdateAsync(T item) { } 46 | 47 | public void UpdatePartial(object item) { } 48 | 49 | public Task UpdatePartialAsync(object item) { } 50 | 51 | public void UpdateRange(IEnumerable items) { } 52 | 53 | public Task UpdateRangeAsync(IEnumerable items) { } 54 | } 55 | ``` 56 | 57 | ### EFQueryRepository 58 | 59 | ```cs 60 | public class EFQueryRepository : IQueryRepository where T : class 61 | { 62 | public EFQueryRepository(DbContext context) { } 63 | 64 | public IQueryable Queryable { get; }; 65 | 66 | public bool Any() { } 67 | 68 | public bool Any(Expression> where) { } 69 | 70 | public Task AnyAsync() { } 71 | 72 | public Task AnyAsync(Expression> where) { } 73 | 74 | public long Count() { } 75 | 76 | public long Count(Expression> where) { } 77 | 78 | public Task CountAsync() { } 79 | 80 | public Task CountAsync(Expression> where) { } 81 | 82 | public T Get(object key) { } 83 | 84 | public Task GetAsync(object key) { } 85 | 86 | public IEnumerable List() { } 87 | 88 | public async Task> ListAsync() { } 89 | } 90 | ``` 91 | 92 | ### EFRepository 93 | 94 | ```cs 95 | public class EFRepository : Repository where T : class 96 | { 97 | public EFRepository(DbContext context) : base(new EFCommandRepository(context), new EFQueryRepository(context)) { } 98 | } 99 | ``` 100 | 101 | ### IUnitOfWork 102 | 103 | ```cs 104 | public interface IUnitOfWork 105 | { 106 | Task SaveChangesAsync(); 107 | } 108 | ``` 109 | 110 | ### UnitOfWork 111 | 112 | ```cs 113 | public sealed class UnitOfWork : IUnitOfWork where TDbContext : DbContext 114 | { 115 | public UnitOfWork(TDbContext context) { } 116 | 117 | public Task SaveChangesAsync() { } 118 | } 119 | ``` 120 | -------------------------------------------------------------------------------- /source/Extensions/AssemblyExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace DotNetCore.Extensions; 4 | 5 | public static class AssemblyExtensions 6 | { 7 | public static FileInfo FileInfo(this Assembly assembly) => new(assembly.Location); 8 | } 9 | -------------------------------------------------------------------------------- /source/Extensions/ByteExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Compression; 2 | using System.Text; 3 | using System.Text.Json; 4 | 5 | namespace DotNetCore.Extensions; 6 | 7 | public static class ByteExtensions 8 | { 9 | public static byte[] Compress(this byte[] bytes) 10 | { 11 | if (bytes is null) return []; 12 | 13 | using var output = new MemoryStream(); 14 | 15 | using var stream = new BrotliStream(output, CompressionMode.Compress); 16 | 17 | stream.Write(bytes, 0, bytes.Length); 18 | 19 | return output.ToArray(); 20 | } 21 | 22 | public static byte[] Decompress(this byte[] bytes) 23 | { 24 | using var input = new MemoryStream(bytes); 25 | 26 | using var stream = new BrotliStream(input, CompressionMode.Decompress); 27 | 28 | using var output = new MemoryStream(); 29 | 30 | stream.CopyTo(output); 31 | 32 | return output.ToArray(); 33 | } 34 | 35 | public static T Object(this byte[] bytes) => JsonSerializer.Deserialize(Encoding.Default.GetString(bytes)); 36 | } 37 | -------------------------------------------------------------------------------- /source/Extensions/ClaimsPrincipalExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | 3 | namespace DotNetCore.Extensions; 4 | 5 | public static class ClaimsPrincipalExtensions 6 | { 7 | public static Claim Claim(this ClaimsPrincipal claimsPrincipal, string claimType) => claimsPrincipal?.FindFirst(claimType); 8 | 9 | public static IEnumerable ClaimRoles(this ClaimsPrincipal claimsPrincipal) => claimsPrincipal?.Claims("role"); 10 | 11 | public static IEnumerable Claims(this ClaimsPrincipal claimsPrincipal, string claimType) => claimsPrincipal?.FindAll(claimType).Select(x => x.Value).ToList(); 12 | 13 | public static string ClaimSub(this ClaimsPrincipal claimsPrincipal) => claimsPrincipal?.Claim("sub")?.Value; 14 | 15 | public static long Id(this ClaimsPrincipal claimsPrincipal) => long.TryParse(claimsPrincipal.ClaimSub(), out var value) ? value : 0; 16 | 17 | public static IEnumerable Roles(this ClaimsPrincipal claimsPrincipal) where T : Enum => claimsPrincipal.ClaimRoles().Select(value => (T)Enum.Parse(typeof(T), value)).ToList(); 18 | 19 | public static T RolesFlag(this ClaimsPrincipal claimsPrincipal) where T : Enum => (T)Enum.Parse(typeof(T), claimsPrincipal.Roles().Sum(value => Convert.ToInt64(value)).ToString(), true); 20 | } 21 | -------------------------------------------------------------------------------- /source/Extensions/DateTimeExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Extensions; 2 | 3 | public static class DateTimeExtensions 4 | { 5 | public static List<(DateTime, DateTime)> Chunks(this DateTime startDate, DateTime endDate, int days) 6 | { 7 | endDate = endDate.Date.AddHours(23).AddMinutes(59).AddSeconds(59); 8 | 9 | var chunks = new List<(DateTime, DateTime)>(); 10 | 11 | var currentDate = startDate; 12 | 13 | while (currentDate <= endDate) 14 | { 15 | var chunkStartDate = currentDate; 16 | 17 | var chunkEndDate = currentDate.AddDays(days).AddHours(23).AddMinutes(59).AddSeconds(59); 18 | 19 | if (chunkEndDate > endDate) chunkEndDate = endDate; 20 | 21 | chunks.Add((chunkStartDate, chunkEndDate)); 22 | 23 | currentDate = chunkEndDate.AddSeconds(1); 24 | } 25 | 26 | return chunks; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /source/Extensions/DirectoryInfoExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Extensions; 2 | 3 | public static class DirectoryInfoExtensions 4 | { 5 | public static FileInfo GetFile(this DirectoryInfo directoryInfo, string name) => directoryInfo?.GetFiles(string.Concat(name, ".", "*")).SingleOrDefault(); 6 | } 7 | -------------------------------------------------------------------------------- /source/Extensions/DotNetCore.Extensions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.Extensions 4 | DotNetCore.Extensions 5 | DotNetCore.Extensions 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/Extensions 7 | Extension, Extensions, Byte, Claim, ClaimsPrincipal, DirectoryInfo, Enum, Object, Queryable, String 8 | DotNetCore.Extensions 9 | 10 | 11 | -------------------------------------------------------------------------------- /source/Extensions/EnumExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace DotNetCore.Extensions; 4 | 5 | public static class EnumExtensions 6 | { 7 | public static string GetDescription(this Enum value) 8 | { 9 | if (value is null) return default; 10 | 11 | var attribute = value.GetAttribute(); 12 | 13 | return attribute is null ? value.ToString() : attribute.Description; 14 | } 15 | 16 | public static string[] ToArray(this Enum value) => value?.ToString().Split(", "); 17 | 18 | private static T GetAttribute(this Enum value) where T : Attribute 19 | { 20 | if (value is null) return default; 21 | 22 | var member = value.GetType().GetMember(value.ToString()); 23 | 24 | var attributes = member[0].GetCustomAttributes(typeof(T), false); 25 | 26 | return (T)attributes[0]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /source/Extensions/ObjectExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Text; 3 | using System.Text.Json; 4 | using System.Text.Json.Serialization; 5 | 6 | namespace DotNetCore.Extensions; 7 | 8 | public static class ObjectExtensions 9 | { 10 | public static byte[] Bytes(this object obj) => Encoding.Default.GetBytes(JsonSerializer.Serialize(obj)); 11 | 12 | public static Dictionary Dictionary(this object obj) 13 | { 14 | if (obj is null) return default; 15 | 16 | var dictionary = new Dictionary(); 17 | 18 | foreach (var property in obj.GetType().GetProperties()) 19 | { 20 | dictionary[property.Name] = property.GetValue(obj); 21 | } 22 | 23 | return dictionary; 24 | } 25 | 26 | public static IEnumerable GetPropertiesWithAttribute(this object obj) where T : Attribute => obj.GetType().GetProperties().Where(property => Attribute.IsDefined(property, typeof(T))); 27 | 28 | public static string Serialize(this object obj) => JsonSerializer.Serialize(obj, new JsonSerializerOptions(JsonSerializerDefaults.Web) { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }); 29 | 30 | public static void SetProperty(this object obj, string name, object value) => obj.GetType().GetProperty(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase)?.SetValue(obj, value); 31 | } 32 | -------------------------------------------------------------------------------- /source/Extensions/QueryableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | 3 | namespace DotNetCore.Extensions; 4 | 5 | public static class QueryableExtensions 6 | { 7 | public static IQueryable Filter(this IQueryable queryable, string property, object value) => queryable.Filter(property, string.Empty, value); 8 | 9 | public static IQueryable Filter(this IQueryable queryable, string property, string comparison, object value) 10 | { 11 | if (string.IsNullOrWhiteSpace(property) || value is null || string.IsNullOrWhiteSpace(value.ToString())) return queryable; 12 | 13 | var parameter = Expression.Parameter(typeof(T)); 14 | 15 | var left = Create(property, parameter); 16 | 17 | try 18 | { 19 | var propertyInfo = typeof(T).GetProperty(property); 20 | 21 | if (propertyInfo is null) return queryable; 22 | 23 | var type = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType; 24 | 25 | value = Change(value, type); 26 | } 27 | catch 28 | { 29 | return Enumerable.Empty().AsQueryable(); 30 | } 31 | 32 | var right = Expression.Constant(value, left.Type); 33 | 34 | var body = Create(left, comparison, right); 35 | 36 | var expression = Expression.Lambda>(body, parameter); 37 | 38 | return queryable.Where(expression); 39 | } 40 | 41 | public static IQueryable Order(this IQueryable queryable, string property, bool ascending) 42 | { 43 | if (queryable is null || string.IsNullOrWhiteSpace(property)) return queryable; 44 | 45 | var parameter = Expression.Parameter(typeof(T)); 46 | 47 | var body = Create(property, parameter); 48 | 49 | dynamic expression = Expression.Lambda(body, parameter); 50 | 51 | return ascending ? Queryable.OrderBy(queryable, expression) : Queryable.OrderByDescending(queryable, expression); 52 | } 53 | 54 | public static IQueryable Page(this IQueryable queryable, int index, int size) => queryable is null || index <= 0 || size <= 0 ? queryable : queryable.Skip((index - 1) * size).Take(size); 55 | 56 | private static object Change(object value, Type type) 57 | { 58 | if (type.BaseType != typeof(Enum)) return Convert.ChangeType(value, type); 59 | 60 | var stringValue = value.ToString(); 61 | 62 | if (stringValue is null) return default; 63 | 64 | value = Enum.Parse(type, stringValue); 65 | 66 | return Convert.ChangeType(value, type); 67 | } 68 | 69 | private static Expression Create(string property, Expression parameter) => property.Split('.').Aggregate(parameter, Expression.Property); 70 | 71 | private static Expression Create(Expression left, string comparison, Expression right) 72 | { 73 | if (string.IsNullOrWhiteSpace(comparison) && left.Type == typeof(string)) 74 | { 75 | return Expression.Call(left, nameof(string.Contains), Type.EmptyTypes, right); 76 | } 77 | 78 | var type = comparison switch 79 | { 80 | "<" => ExpressionType.LessThan, 81 | "<=" => ExpressionType.LessThanOrEqual, 82 | ">" => ExpressionType.GreaterThan, 83 | ">=" => ExpressionType.GreaterThanOrEqual, 84 | "!=" => ExpressionType.NotEqual, 85 | _ => ExpressionType.Equal 86 | }; 87 | 88 | return Expression.MakeBinary(type, left, right); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /source/Extensions/StreamExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Extensions; 2 | 3 | public static class StreamExtensions 4 | { 5 | public static string ToBase64String(this Stream stream) 6 | { 7 | using var memoryStream = new MemoryStream(); 8 | 9 | stream.CopyTo(memoryStream); 10 | 11 | return Convert.ToBase64String(memoryStream.ToArray()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /source/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Mail; 2 | using System.Numerics; 3 | using System.Text; 4 | using System.Text.Json; 5 | using System.Text.Json.Serialization; 6 | using System.Text.RegularExpressions; 7 | 8 | namespace DotNetCore.Extensions; 9 | 10 | public static class StringExtensions 11 | { 12 | public static T Deserialize(this string value) where T : class 13 | { 14 | return string.IsNullOrWhiteSpace(value) 15 | ? default 16 | : JsonSerializer.Deserialize(value, new JsonSerializerOptions(JsonSerializerDefaults.Web) 17 | { 18 | NumberHandling = JsonNumberHandling.AllowReadingFromString, 19 | PropertyNameCaseInsensitive = true 20 | }); 21 | } 22 | 23 | public static string ExtractNumbers(this string value) => string.IsNullOrWhiteSpace(value) ? value : Regex.Replace(value, "[^0-9]", string.Empty); 24 | 25 | public static bool IsDate(this string value) => !string.IsNullOrWhiteSpace(value) && DateOnly.TryParseExact(value, "dd/MM/yyyy", out _); 26 | 27 | public static bool IsEmail(this string value) => !string.IsNullOrWhiteSpace(value) && MailAddress.TryCreate(value, out _); 28 | 29 | public static bool IsInteger(this string value) => !string.IsNullOrWhiteSpace(value) && BigInteger.TryParse(value, out _); 30 | 31 | public static bool IsLogin(this string value) => !string.IsNullOrWhiteSpace(value) && new Regex("^[a-z0-9._-]{10,50}$").IsMatch(value); 32 | 33 | public static bool IsNumber(this string value) => !string.IsNullOrWhiteSpace(value) && decimal.TryParse(value, out _); 34 | 35 | public static bool IsPassword(this string value) => !string.IsNullOrWhiteSpace(value) && new Regex(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^a-zA-Z\d\s]).{10,50}$").IsMatch(value); 36 | 37 | public static bool IsTime(this string value) => !string.IsNullOrWhiteSpace(value) && TimeOnly.TryParseExact(value, "HH:mm:ss", out _); 38 | 39 | public static bool IsUrl(this string value) => !string.IsNullOrWhiteSpace(value) && Uri.TryCreate(value, UriKind.RelativeOrAbsolute, out _); 40 | 41 | public static string RemoveAccents(this string value) => string.IsNullOrWhiteSpace(value) ? value : Encoding.ASCII.GetString(Encoding.GetEncoding("Cyrillic").GetBytes(value)); 42 | 43 | public static string RemoveDuplicateSpaces(this string value) => string.IsNullOrWhiteSpace(value) ? value : Regex.Replace(value, @"\s+", " "); 44 | 45 | public static string RemoveSpecialCharacters(this string value) => string.IsNullOrWhiteSpace(value) ? value : Regex.Replace(value, "[^0-9a-zA-Z ]+", string.Empty); 46 | 47 | public static string Sanitize(this string value) => string.IsNullOrWhiteSpace(value) ? value : value.RemoveSpecialCharacters().RemoveDuplicateSpaces().RemoveAccents(); 48 | } 49 | -------------------------------------------------------------------------------- /source/Extensions/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.Extensions 2 | 3 | ## AssemblyExtensions 4 | 5 | ```cs 6 | public static class AssemblyExtensions 7 | { 8 | public static FileInfo FileInfo(this Assembly assembly) { } 9 | } 10 | ``` 11 | 12 | ## ByteExtensions 13 | 14 | ```cs 15 | public static class ByteExtensions 16 | { 17 | public static byte[] Compress(this byte[] bytes) { } 18 | 19 | public static byte[] Decompress(this byte[] bytes) { } 20 | 21 | public static T Object(this byte[] bytes) { } 22 | } 23 | ``` 24 | 25 | ## ClaimsPrincipalExtensions 26 | 27 | ```cs 28 | public static class ClaimsPrincipalExtensions 29 | { 30 | public static Claim Claim(this ClaimsPrincipal claimsPrincipal, string claimType) { } 31 | 32 | public static IEnumerable ClaimRoles(this ClaimsPrincipal claimsPrincipal) { } 33 | 34 | public static IEnumerable Claims(this ClaimsPrincipal claimsPrincipal, string claimType) { } 35 | 36 | public static string ClaimSub(this ClaimsPrincipal claimsPrincipal) { } 37 | 38 | public static long Id(this ClaimsPrincipal claimsPrincipal) { } 39 | 40 | public static IEnumerable Roles(this ClaimsPrincipal claimsPrincipal) where T : Enum { } 41 | 42 | public static T RolesFlag(this ClaimsPrincipal claimsPrincipal) where T : Enum { } 43 | } 44 | ``` 45 | 46 | ## DateTimeExtensions 47 | 48 | ```cs 49 | public static class DateTimeExtensions 50 | { 51 | public static List<(DateTime, DateTime)> Chunks(this DateTime startDate, DateTime endDate, int days) { } 52 | } 53 | ``` 54 | 55 | ## DirectoryInfoExtensions 56 | 57 | ```cs 58 | public static class DirectoryInfoExtensions 59 | { 60 | public static FileInfo GetFile(this DirectoryInfo directoryInfo, string name) { } 61 | } 62 | ``` 63 | 64 | ## EnumExtensions 65 | 66 | ```cs 67 | public static class EnumExtensions 68 | { 69 | public static string GetDescription(this Enum value) { } 70 | 71 | public static string[] ToArray(this Enum value) { } 72 | } 73 | ``` 74 | 75 | ## ObjectExtensions 76 | 77 | ```cs 78 | public static class ObjectExtensions 79 | { 80 | public static byte[] Bytes(this object obj) { } 81 | 82 | public static Dictionary Dictionary(this object obj) { } 83 | 84 | public static IEnumerable GetPropertiesWithAttribute(this object obj) where T : Attribute { } 85 | 86 | public static string Serialize(this object obj) { } 87 | 88 | public static void SetProperty(this object obj, string name, object value) { } 89 | } 90 | ``` 91 | 92 | ## QueryableExtensions 93 | 94 | ```cs 95 | public static class QueryableExtensions 96 | { 97 | public static IQueryable Filter(this IQueryable queryable, string property, object value) { } 98 | 99 | public static IQueryable Filter(this IQueryable queryable, string property, string comparison, object value) { } 100 | 101 | public static IQueryable Order(this IQueryable queryable, string property, bool ascending) { } 102 | 103 | public static IQueryable Page(this IQueryable queryable, int index, int size) { } 104 | } 105 | ``` 106 | 107 | ## StreamExtensions 108 | 109 | ```cs 110 | public static class StreamExtensions 111 | { 112 | public static string ToBase64String(this Stream stream) { } 113 | } 114 | ``` 115 | 116 | ## StringExtensions 117 | 118 | ```cs 119 | public static class StringExtensions 120 | { 121 | public static T Deserialize(this string value) where T : class { } 122 | 123 | public static string ExtractNumbers(this string value) { } 124 | 125 | public static bool IsDate(this string value) { } 126 | 127 | public static bool IsEmail(this string value) { } 128 | 129 | public static bool IsInteger(this string value) { } 130 | 131 | public static bool IsLogin(this string value) { } 132 | 133 | public static bool IsNumber(this string value) { } 134 | 135 | public static bool IsPassword(this string value) { } 136 | 137 | public static bool IsTime(this string value) { } 138 | 139 | public static bool IsUrl(this string value) { } 140 | 141 | public static string RemoveAccents(this string value) { } 142 | 143 | public static string RemoveDuplicateSpaces(this string value) { } 144 | 145 | public static string RemoveSpecialCharacters(this string value) { } 146 | 147 | public static string Sanitize(this string value) { } 148 | } 149 | ``` 150 | -------------------------------------------------------------------------------- /source/IoC/DotNetCore.IoC.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.IoC 4 | DotNetCore.IoC 5 | DotNetCore.IoC 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/IoC 7 | DI, DependencyInjection, IoC, InversionOfControl 8 | DotNetCore.IoC 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /source/IoC/Extensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.DependencyModel; 4 | using Scrutor; 5 | using System.Reflection; 6 | 7 | namespace DotNetCore.IoC; 8 | 9 | public static class Extensions 10 | { 11 | public static T AddAppSettings(this IServiceCollection services) where T : class 12 | { 13 | var appSettings = new ConfigurationBuilder().Configuration().Get(); 14 | 15 | services.AddSingleton(appSettings); 16 | 17 | return appSettings; 18 | } 19 | 20 | public static T AddAppSettings(this IServiceCollection services, string section) where T : class 21 | { 22 | var appSettings = new ConfigurationBuilder().Configuration().GetSection(section).Get(); 23 | 24 | services.AddSingleton(appSettings); 25 | 26 | return appSettings; 27 | } 28 | 29 | public static void AddClassesMatchingInterfaces(this IServiceCollection services, string @namespace) 30 | { 31 | var assemblies = DependencyContext.Default.GetDefaultAssemblyNames().Where(assembly => assembly.FullName.StartsWith(@namespace)).Select(Assembly.Load); 32 | 33 | services.Scan(scan => scan.FromAssemblies(assemblies).AddClasses().UsingRegistrationStrategy(RegistrationStrategy.Skip).AsMatchingInterface().WithScopedLifetime()); 34 | } 35 | 36 | public static IConfigurationRoot Configuration(this IConfigurationBuilder configuration) => configuration.AddJsonFile("AppSettings.json", false, true).AddEnvironmentVariables().Build(); 37 | 38 | public static string GetConnectionString(this IServiceCollection services, string name) => services.BuildServiceProvider().GetRequiredService().GetConnectionString(name); 39 | } 40 | -------------------------------------------------------------------------------- /source/IoC/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.IoC 2 | 3 | ## Extensions 4 | 5 | ```cs 6 | public static class Extensions 7 | { 8 | public static T AddAppSettings(this IServiceCollection services) where T : class { } 9 | 10 | public static T AddAppSettings(this IServiceCollection services, string section) where T : class { } 11 | 12 | public static void AddClassesMatchingInterfaces(this IServiceCollection services, string @namespace) { } 13 | 14 | public static IConfigurationRoot Configuration(this IConfigurationBuilder configuration) { } 15 | 16 | public static string GetConnectionString(this IServiceCollection services, string name) { } 17 | } 18 | ``` 19 | -------------------------------------------------------------------------------- /source/Logging/DotNetCore.Logging.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.Logging 4 | DotNetCore.Logging 5 | DotNetCore.Logging 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/Logging 7 | Log, Logging, Logger 8 | DotNetCore.Logging 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /source/Logging/Extensions.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.IoC; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | using Serilog; 6 | 7 | namespace DotNetCore.Logging; 8 | 9 | public static class Extensions 10 | { 11 | public static void Log(this Microsoft.Extensions.Logging.ILogger logger, HttpResponseMessage response) => logger.Log 12 | ( 13 | response.IsSuccessStatusCode ? LogLevel.Information : LogLevel.Error, 14 | "{Url} {Method} {Request} {Response}", 15 | response.RequestMessage?.RequestUri, 16 | response.RequestMessage?.Method, 17 | response.RequestMessage?.Content?.ReadAsStringAsync().Result, 18 | response.Content.ReadAsStringAsync().Result 19 | ); 20 | 21 | public static IHostBuilder UseSerilog(this IHostBuilder builder) 22 | { 23 | var configuration = new ConfigurationBuilder().Configuration(); 24 | 25 | Serilog.Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger(); 26 | 27 | SerilogHostBuilderExtensions.UseSerilog(builder); 28 | 29 | return builder; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /source/Logging/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.Logging 2 | 3 | ## Extensions 4 | 5 | ```cs 6 | public static class Extensions 7 | { 8 | public static void Log(this ILogger logger, HttpResponseMessage response) { } 9 | 10 | public static IHostBuilder UseSerilog(this IHostBuilder builder) { } 11 | } 12 | ``` 13 | -------------------------------------------------------------------------------- /source/Mapping/DotNetCore.Mapping.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.Mapping 4 | DotNetCore.Mapping 5 | DotNetCore.Mapping 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/Mapping 7 | Map, Mapping, Mapper, Clone, Merge, ObjectMap, ObjectMapping, ObjectMapper, ObjectClone, ObjectMerge 8 | DotNetCore.Mapping 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /source/Mapping/Extensions.cs: -------------------------------------------------------------------------------- 1 | using AgileObjects.AgileMapper; 2 | 3 | namespace DotNetCore.Mapping; 4 | 5 | public static class Extensions 6 | { 7 | public static TSource Clone(this TSource source) => source is null ? default : Mapper.DeepClone(source); 8 | 9 | public static TDestination Map(this TSource source) => source is null ? default : Mapper.Map(source).ToANew(); 10 | 11 | public static TDestination Map(this object source) => source is null ? default : Mapper.Map(source).ToANew(); 12 | 13 | public static TDestination Map(this TSource source, TDestination destination) => Mapper.Map(source).OnTo(destination); 14 | 15 | public static IQueryable Project(this IQueryable queryable) => queryable.Project().To(); 16 | } 17 | -------------------------------------------------------------------------------- /source/Mapping/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.Mapping 2 | 3 | ## Extensions 4 | 5 | ```cs 6 | public static class Extensions 7 | { 8 | public static TSource Clone(this TSource source) { } 9 | 10 | public static TDestination Map(this TSource source) { } 11 | 12 | public static TDestination Map(this object source) { } 13 | 14 | public static TDestination Map(this TSource source, TDestination destination) { } 15 | 16 | public static IQueryable Project(this IQueryable queryable) { } 17 | } 18 | ``` 19 | -------------------------------------------------------------------------------- /source/Mediator/DotNetCore.Mediator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.Mediator 4 | DotNetCore.Mediator 5 | DotNetCore.Mediator 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/Mediator 7 | Mediator, MediatorPattern, Pattern, CQRS, Command, CommandHandler, Query, QueryHandler, Handler, Request, Response 8 | DotNetCore.Mediator 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /source/Mediator/Extensions.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using Microsoft.Extensions.DependencyModel; 4 | using System.Reflection; 5 | 6 | namespace DotNetCore.Mediator; 7 | 8 | public static class Extensions 9 | { 10 | public static void AddMediator(this IServiceCollection services, string @namespace) 11 | { 12 | services.AddScoped(); 13 | 14 | var assemblies = DependencyContext.Default!.GetDefaultAssemblyNames().Where(assembly => assembly.FullName.StartsWith(@namespace)).Select(Assembly.Load); 15 | 16 | var types = assemblies.SelectMany(assembly => assembly.GetTypes()).ToList(); 17 | 18 | types.Where(type => type.GetInterfaces().Any(IsHandler)).ToList().ForEach(type => type.GetInterfaces().Where(IsHandler).ToList().ForEach(@interface => services.AddScoped(@interface, type))); 19 | 20 | types.Where(type => IsType(type.BaseType, typeof(AbstractValidator<>))).ToList().ForEach(type => services.AddSingleton(type.BaseType!, type)); 21 | 22 | return; 23 | 24 | static bool IsHandler(Type type) => IsType(type, typeof(IHandler<>)) || IsType(type, typeof(IHandler<,>)); 25 | 26 | static bool IsType(Type type, MemberInfo memberInfo) => type is not null && type.IsGenericType && type.GetGenericTypeDefinition() == memberInfo; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /source/Mediator/IHandler.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Results; 2 | 3 | namespace DotNetCore.Mediator; 4 | 5 | public interface IHandler 6 | { 7 | Task HandleAsync(TRequest request); 8 | } 9 | 10 | public interface IHandler 11 | { 12 | Task> HandleAsync(TRequest request); 13 | } 14 | -------------------------------------------------------------------------------- /source/Mediator/IMediator.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Results; 2 | 3 | namespace DotNetCore.Mediator; 4 | 5 | public interface IMediator 6 | { 7 | Task HandleAsync(TRequest request); 8 | 9 | Task> HandleAsync(TRequest request); 10 | } 11 | -------------------------------------------------------------------------------- /source/Mediator/Mediator.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Results; 2 | using FluentValidation; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using System.Net; 5 | 6 | namespace DotNetCore.Mediator; 7 | 8 | public sealed class Mediator(IServiceProvider serviceProvider) : IMediator 9 | { 10 | public async Task HandleAsync(TRequest request) 11 | { 12 | var (valid, message) = Validate(request); 13 | 14 | if (!valid) return new Result(HttpStatusCode.BadRequest, message); 15 | 16 | var handler = serviceProvider.GetRequiredService>(); 17 | 18 | return await handler.HandleAsync(request).ConfigureAwait(false); 19 | } 20 | 21 | public async Task> HandleAsync(TRequest request) 22 | { 23 | var (valid, message) = Validate(request); 24 | 25 | if (!valid) return new Result(HttpStatusCode.BadRequest, message); 26 | 27 | var handler = serviceProvider.GetRequiredService>(); 28 | 29 | return await handler.HandleAsync(request).ConfigureAwait(false); 30 | } 31 | 32 | private (bool, string) Validate(TRequest request) 33 | { 34 | var validator = serviceProvider.GetService>(); 35 | 36 | if (validator is null) return (true, default); 37 | 38 | var validation = validator.Validate(request); 39 | 40 | return (validation.IsValid, validation.ToString()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /source/Mediator/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.Mediator 2 | 3 | The smallest, simplest and fastest implementation of the mediator pattern. 4 | 5 | ## ASP.NET Core Startup Example 6 | 7 | ```cs 8 | public sealed class Startup 9 | { 10 | public void ConfigureServices(IServiceCollection services) 11 | { 12 | services.AddMediator("Namespace"); 13 | } 14 | } 15 | ``` 16 | 17 | ## ASP.NET Core Controller Example 18 | 19 | ```cs 20 | public sealed class Controller : ControllerBase 21 | { 22 | private readonly IMediator _mediator; 23 | 24 | public Controller(IMediator mediator) 25 | { 26 | _mediator = mediator; 27 | } 28 | } 29 | ``` 30 | 31 | ## Mediator 32 | 33 | ```cs 34 | public interface IMediator 35 | { 36 | Task HandleAsync(TRequest request); 37 | 38 | Task> HandleAsync(TRequest request); 39 | } 40 | ``` 41 | 42 | ```cs 43 | public sealed class Mediator : IMediator 44 | { 45 | public async Task HandleAsync(TRequest request) { } 46 | 47 | public async Task> HandleAsync(TRequest request) { } 48 | } 49 | ``` 50 | 51 | ```cs 52 | public interface IHandler 53 | { 54 | Task HandleAsync(TRequest request); 55 | } 56 | ``` 57 | 58 | ```cs 59 | public interface IHandler 60 | { 61 | Task> HandleAsync(TRequest request); 62 | } 63 | ``` 64 | -------------------------------------------------------------------------------- /source/MongoDB/Context/IMongoContext.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Driver; 2 | 3 | namespace DotNetCore.MongoDB; 4 | 5 | public interface IMongoContext 6 | { 7 | IMongoDatabase Database { get; } 8 | } 9 | -------------------------------------------------------------------------------- /source/MongoDB/Context/MongoContext.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Driver; 2 | 3 | namespace DotNetCore.MongoDB; 4 | 5 | public abstract class MongoContext(string connectionString) : IMongoContext 6 | { 7 | public IMongoDatabase Database { get; } = new MongoClient(connectionString).GetDatabase(new MongoUrl(connectionString).DatabaseName); 8 | } 9 | -------------------------------------------------------------------------------- /source/MongoDB/Document/Document.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson; 2 | using MongoDB.Bson.Serialization.Attributes; 3 | 4 | namespace DotNetCore.MongoDB; 5 | 6 | public abstract class Document : IDocument 7 | { 8 | [BsonExtraElements] 9 | public BsonDocument ExtraElements { get; set; } 10 | 11 | public ObjectId Id { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /source/MongoDB/Document/IDocument.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Bson; 2 | 3 | namespace DotNetCore.MongoDB; 4 | 5 | public interface IDocument 6 | { 7 | ObjectId Id { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /source/MongoDB/DotNetCore.MongoDB.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.MongoDB 4 | DotNetCore.MongoDB 5 | DotNetCore.MongoDB 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/MongoDB 7 | ORM, ObjectRelationalMapping, Mongo MongoDB, Context, Repository, GenericRepository, BaseRepository, RepositoryBase, CommandRepository, QueryRepository, CQRS, Command, Query 8 | DotNetCore.MongoDB 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /source/MongoDB/Filters.cs: -------------------------------------------------------------------------------- 1 | using MongoDB.Driver; 2 | 3 | namespace DotNetCore.MongoDB; 4 | 5 | public static class Filters 6 | { 7 | public static FilterDefinition Id(object value) => Builders.Filter.Eq(nameof(Id), value); 8 | } 9 | -------------------------------------------------------------------------------- /source/MongoDB/Repository/MongoCommandRepository.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Repositories; 2 | using MongoDB.Driver; 3 | using System.Linq.Expressions; 4 | 5 | namespace DotNetCore.MongoDB; 6 | 7 | public class MongoCommandRepository(IMongoContext context) : ICommandRepository where T : class 8 | { 9 | private readonly IMongoCollection _collection = context.Database.GetCollection(typeof(T).Name); 10 | 11 | public void Add(T item) => _collection.InsertOne(item); 12 | 13 | public Task AddAsync(T item) => _collection.InsertOneAsync(item); 14 | 15 | public void AddRange(IEnumerable items) => _collection.InsertMany(items); 16 | 17 | public Task AddRangeAsync(IEnumerable items) => _collection.InsertManyAsync(items); 18 | 19 | public void Delete(object key) => _collection.DeleteOne(Filters.Id(key)); 20 | 21 | public void Delete(Expression> where) => _collection.DeleteMany(where); 22 | 23 | public Task DeleteAsync(object key) => _collection.DeleteOneAsync(Filters.Id(key)); 24 | 25 | public Task DeleteAsync(Expression> where) => _collection.DeleteManyAsync(where); 26 | 27 | public void Update(T item) => _collection.ReplaceOne(Filters.Id(GetKey(item)), item); 28 | 29 | public Task UpdateAsync(T item) => _collection.ReplaceOneAsync(Filters.Id(GetKey(item)), item); 30 | 31 | public void UpdatePartial(object item) => _collection.ReplaceOne(Filters.Id(GetKey(item)), item as T); 32 | 33 | public Task UpdatePartialAsync(object item) => _collection.ReplaceOneAsync(Filters.Id(GetKey(item)), item as T); 34 | 35 | public void UpdateRange(IEnumerable items) => _collection.BulkWrite(WriteModels(items)); 36 | 37 | public Task UpdateRangeAsync(IEnumerable items) => _collection.BulkWriteAsync(WriteModels(items)); 38 | 39 | private static IEnumerable> WriteModels(IEnumerable items) => items.Select(item => new ReplaceOneModel(Filters.Id(GetKey(item)), item) { IsUpsert = true }); 40 | 41 | private static object GetKey(object item) => item.GetType().GetProperty("Id")?.GetValue(item, default); 42 | } 43 | -------------------------------------------------------------------------------- /source/MongoDB/Repository/MongoQueryRepository.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Repositories; 2 | using MongoDB.Driver; 3 | using MongoDB.Driver.Linq; 4 | using System.Linq.Expressions; 5 | 6 | namespace DotNetCore.MongoDB; 7 | 8 | public class MongoQueryRepository(IMongoContext context) : IQueryRepository where T : class 9 | { 10 | private readonly IMongoCollection _collection = context.Database.GetCollection(typeof(T).Name); 11 | 12 | public IQueryable Queryable => _collection.AsQueryable(); 13 | 14 | public bool Any() => Queryable.Any(); 15 | 16 | public bool Any(Expression> where) => Queryable.Where(where).Any(); 17 | 18 | public Task AnyAsync() => Queryable.AnyAsync(); 19 | 20 | public Task AnyAsync(Expression> where) => Queryable.Where(where).AnyAsync(); 21 | 22 | public long Count() => Queryable.LongCount(); 23 | 24 | public long Count(Expression> where) => Queryable.Where(where).LongCount(); 25 | 26 | public Task CountAsync() => Queryable.LongCountAsync(); 27 | 28 | public Task CountAsync(Expression> where) => Queryable.Where(where).LongCountAsync(); 29 | 30 | public T Get(object key) => _collection.Find(Filters.Id(key)).SingleOrDefault(); 31 | 32 | public Task GetAsync(object key) => _collection.Find(Filters.Id(key)).SingleOrDefaultAsync(); 33 | 34 | public IEnumerable List() => Queryable.ToList(); 35 | 36 | public async Task> ListAsync() => await Queryable.ToListAsync().ConfigureAwait(false); 37 | } 38 | -------------------------------------------------------------------------------- /source/MongoDB/Repository/MongoRepository.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Repositories; 2 | 3 | namespace DotNetCore.MongoDB; 4 | 5 | public class MongoRepository(IMongoContext context) : Repository(new MongoCommandRepository(context), new MongoQueryRepository(context)) where T : class; 6 | -------------------------------------------------------------------------------- /source/MongoDB/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.MongoDB 2 | 3 | ## Context 4 | 5 | ### IMongoContext 6 | 7 | ```cs 8 | public interface IMongoContext 9 | { 10 | IMongoDatabase Database { get; } 11 | } 12 | ``` 13 | 14 | ### MongoContext 15 | 16 | ```cs 17 | public abstract class MongoContext : IMongoContext 18 | { 19 | public MongoContext(string connectionString) { } 20 | 21 | public IMongoDatabase Database { get; } 22 | } 23 | ``` 24 | 25 | ## Document 26 | 27 | ### IDocument 28 | 29 | ```cs 30 | public interface IDocument 31 | { 32 | ObjectId Id { get; set; } 33 | } 34 | ``` 35 | 36 | ### Document 37 | 38 | ```cs 39 | public abstract class Document : IDocument 40 | { 41 | [BsonExtraElements] 42 | public BsonDocument ExtraElements { get; set; } 43 | 44 | public ObjectId Id { get; set; } 45 | } 46 | ``` 47 | 48 | ## MongoCommandRepository 49 | 50 | ```cs 51 | public class MongoCommandRepository : ICommandRepository where T : class 52 | { 53 | public MongoCommandRepository(IMongoContext context) { } 54 | 55 | public void Add(T item) { } 56 | 57 | public Task AddAsync(T item) { } 58 | 59 | public void AddRange(IEnumerable items) { } 60 | 61 | public Task AddRangeAsync(IEnumerable items) { } 62 | 63 | public void Delete(object key) { } 64 | 65 | public void Delete(Expression> where) { } 66 | 67 | public Task DeleteAsync(object key) { } 68 | 69 | public Task DeleteAsync(Expression> where) { } 70 | 71 | public void Update(T item) { } 72 | 73 | public Task UpdateAsync(T item) { } 74 | 75 | public void UpdatePartial(object item) { } 76 | 77 | public Task UpdatePartialAsync(object item) { } 78 | 79 | public void UpdateRange(IEnumerable items) { } 80 | 81 | public Task UpdateRangeAsync(IEnumerable items) { } 82 | } 83 | ``` 84 | 85 | ## MongoQueryRepository 86 | 87 | ```cs 88 | public class MongoQueryRepository : IQueryRepository where T : class 89 | { 90 | public MongoQueryRepository(IMongoContext context) { } 91 | 92 | public IQueryable Queryable { get; }; 93 | 94 | public bool Any() { } 95 | 96 | public bool Any(Expression> where) { } 97 | 98 | public Task AnyAsync() { } 99 | 100 | public Task AnyAsync(Expression> where) { } 101 | 102 | public long Count() { } 103 | 104 | public long Count(Expression> where) { } 105 | 106 | public Task CountAsync() { } 107 | 108 | public Task CountAsync(Expression> where) { } 109 | 110 | public T Get(object key) { } 111 | 112 | public Task GetAsync(object key) { } 113 | 114 | public IEnumerable List() { } 115 | 116 | public async Task> ListAsync() { } 117 | } 118 | ``` 119 | 120 | ## MongoRepository 121 | 122 | ```cs 123 | public class MongoRepository : Repository where T : class 124 | { 125 | public MongoRepository(IMongoContext context) : base(new MongoCommandRepository(context), new MongoQueryRepository(context)) { } 126 | } 127 | ``` 128 | -------------------------------------------------------------------------------- /source/Objects/DotNetCore.Objects.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.Objects 4 | DotNetCore.Objects 5 | DotNetCore.Objects 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/Objects 7 | Object, DTO, DataTransferObject 8 | DotNetCore.Objects 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /source/Objects/File/BinaryFile.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Extensions; 2 | 3 | namespace DotNetCore.Objects; 4 | 5 | public class BinaryFile(Guid id, string name, byte[] bytes, long length, string contentType) 6 | { 7 | public Guid Id { get; } = id; 8 | 9 | public string Name { get; } = name; 10 | 11 | public byte[] Bytes { get; private set; } = bytes; 12 | 13 | public long Length { get; } = length; 14 | 15 | public string ContentType { get; } = contentType; 16 | 17 | public static async Task ReadAsync(string directory, Guid id) 18 | { 19 | if (!Directory.Exists(directory) || id == Guid.Empty) return null; 20 | 21 | var file = new DirectoryInfo(directory).GetFile(id.ToString()); 22 | 23 | if (file is null) return null; 24 | 25 | var bytes = await File.ReadAllBytesAsync(file.FullName).ConfigureAwait(false); 26 | 27 | return new BinaryFile(id, file.Name, bytes, file.Length, file.Extension); 28 | } 29 | 30 | public async Task SaveAsync(string directory) 31 | { 32 | if (string.IsNullOrWhiteSpace(directory) || string.IsNullOrWhiteSpace(Name) || Bytes is null || Bytes.LongLength == 0) return; 33 | 34 | Directory.CreateDirectory(directory); 35 | 36 | var name = string.Concat(Id, Path.GetExtension(Name)); 37 | 38 | var path = Path.Combine(directory, name); 39 | 40 | await File.WriteAllBytesAsync(path, Bytes).ConfigureAwait(false); 41 | 42 | Bytes = default; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /source/Objects/File/BinaryFileExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Objects; 2 | 3 | public static class BinaryFileExtensions 4 | { 5 | public static async Task> SaveAsync(this IEnumerable files, string directory) 6 | { 7 | if (string.IsNullOrWhiteSpace(directory)) return null; 8 | 9 | var binaryFiles = files as BinaryFile[] ?? files.ToArray(); 10 | 11 | await Task.WhenAll(binaryFiles.Select(file => file.SaveAsync(directory))); 12 | 13 | return binaryFiles; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /source/Objects/Grid/Filter.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Objects; 2 | 3 | public record Filter 4 | { 5 | public string Property { get; set; } 6 | 7 | public string Comparison { get; set; } 8 | 9 | public string Value { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /source/Objects/Grid/Filters.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Objects; 2 | 3 | public sealed class Filters : List; 4 | -------------------------------------------------------------------------------- /source/Objects/Grid/Grid.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Extensions; 2 | 3 | namespace DotNetCore.Objects; 4 | 5 | public record Grid 6 | { 7 | public Grid(IQueryable queryable, GridParameters parameters) 8 | { 9 | Parameters = parameters; 10 | 11 | if (queryable is null || parameters is null) return; 12 | 13 | queryable = Filter(queryable, parameters.Filters); 14 | 15 | Count = queryable.LongCount(); 16 | 17 | queryable = Order(queryable, parameters.Order); 18 | 19 | queryable = Page(queryable, parameters.Page); 20 | 21 | List = queryable.AsEnumerable(); 22 | } 23 | 24 | public long Count { get; } 25 | 26 | public IEnumerable List { get; } 27 | 28 | public GridParameters Parameters { get; } 29 | 30 | private static IQueryable Filter(IQueryable queryable, Filters filters) => filters is null ? queryable : filters.Aggregate(queryable, (current, filter) => current.Filter(filter.Property, filter.Comparison, filter.Value)); 31 | 32 | private static IQueryable Order(IQueryable queryable, Order order) => order is null ? queryable : queryable.Order(order.Property, order.Ascending); 33 | 34 | private static IQueryable Page(IQueryable queryable, Page page) => page is null ? queryable : queryable.Page(page.Index, page.Size); 35 | } 36 | -------------------------------------------------------------------------------- /source/Objects/Grid/GridExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Objects; 2 | 3 | public static class GridExtensions 4 | { 5 | public static Grid Grid(this IQueryable queryable, GridParameters parameters) 6 | { 7 | var grid = new Grid(queryable, parameters); 8 | 9 | return grid.List.Any() ? grid : default; 10 | } 11 | 12 | public static Task> GridAsync(this IQueryable queryable, GridParameters parameters) => Task.FromResult(Grid(queryable, parameters)); 13 | } 14 | -------------------------------------------------------------------------------- /source/Objects/Grid/GridParameters.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Objects; 2 | 3 | public record GridParameters 4 | { 5 | public Filters Filters { get; set; } 6 | 7 | public Order Order { get; set; } 8 | 9 | public Page Page { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /source/Objects/Grid/Order.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Objects; 2 | 3 | public record Order 4 | { 5 | public bool Ascending { get; set; } = true; 6 | 7 | public string Property { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /source/Objects/Grid/Page.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Objects; 2 | 3 | public record Page 4 | { 5 | public int Index { get; set; } = 1; 6 | 7 | public int Size { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /source/Objects/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.Objects 2 | 3 | ## BinaryFile 4 | 5 | ```cs 6 | public class BinaryFile 7 | { 8 | public BinaryFile(Guid id, string name, byte[] bytes, long length, string contentType) { } 9 | 10 | public Guid Id { get; } 11 | 12 | public string Name { get; } 13 | 14 | public byte[] Bytes { get; private set; } 15 | 16 | public long Length { get; } 17 | 18 | public string ContentType { get; } 19 | 20 | public static async Task ReadAsync(string directory, Guid id) { } 21 | 22 | public async Task SaveAsync(string directory) { } 23 | } 24 | ``` 25 | 26 | ## BinaryFileExtensions 27 | 28 | ```cs 29 | public static class BinaryFileExtensions 30 | { 31 | public static async Task> SaveAsync(this IEnumerable files, string directory) { } 32 | } 33 | ``` 34 | 35 | ## Filter 36 | 37 | ```cs 38 | public record Filter 39 | { 40 | public string Property { get; set; } 41 | 42 | public string Comparison { get; set; } 43 | 44 | public string Value { get; set; } 45 | } 46 | ``` 47 | 48 | ## Filters 49 | 50 | ```cs 51 | public class Filters : List { } 52 | ``` 53 | 54 | ## Order 55 | 56 | ```cs 57 | public record Order 58 | { 59 | public bool Ascending { get; set; } = true; 60 | 61 | public string Property { get; set; } 62 | } 63 | ``` 64 | 65 | ## Page 66 | 67 | ```cs 68 | public record Page 69 | { 70 | public int Index { get; set; } = 1; 71 | 72 | public int Size { get; set; } 73 | } 74 | ``` 75 | 76 | ## GridParameters 77 | 78 | ```cs 79 | public record GridParameters 80 | { 81 | public Filters Filters { get; set; } 82 | 83 | public Order Order { get; set; } 84 | 85 | public Page Page { get; set; } 86 | } 87 | ``` 88 | 89 | ## Grid 90 | 91 | ```cs 92 | public record Grid 93 | { 94 | public Grid(IQueryable queryable, GridParameters parameters) { } 95 | 96 | public long Count { get; } 97 | 98 | public IEnumerable List { get; } 99 | 100 | public GridParameters Parameters { get; } 101 | } 102 | ``` 103 | 104 | ## GridExtensions 105 | 106 | ```cs 107 | public static class GridExtensions 108 | { 109 | public static Grid Grid(this IQueryable queryable, GridParameters parameters) { } 110 | 111 | public static Task> GridAsync(this IQueryable queryable, GridParameters parameters) { } 112 | } 113 | ``` 114 | -------------------------------------------------------------------------------- /source/RabbitMQ/Connection.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.RabbitMQ; 2 | 3 | public sealed record Connection(string HostName, int Port, string UserName, string Password); 4 | -------------------------------------------------------------------------------- /source/RabbitMQ/DotNetCore.RabbitMQ.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.RabbitMQ 4 | DotNetCore.RabbitMQ 5 | DotNetCore.RabbitMQ 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/RabbitMQ 7 | RabbitMQ, Queue, Broker, MessageBroker 8 | DotNetCore.RabbitMQ 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /source/RabbitMQ/IQueue.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.RabbitMQ; 2 | 3 | public interface IQueue 4 | { 5 | Task PublishAsync(T obj); 6 | 7 | Task SubscribeAsync(Func action); 8 | } 9 | -------------------------------------------------------------------------------- /source/RabbitMQ/Queue.cs: -------------------------------------------------------------------------------- 1 | using DotNetCore.Extensions; 2 | using RabbitMQ.Client; 3 | using RabbitMQ.Client.Events; 4 | 5 | namespace DotNetCore.RabbitMQ; 6 | 7 | public abstract class Queue(Connection connection) : IQueue 8 | { 9 | private readonly ConnectionFactory _connectionFactory = new() 10 | { 11 | HostName = connection.HostName, 12 | Port = connection.Port, 13 | UserName = connection.UserName, 14 | Password = connection.Password 15 | }; 16 | 17 | public async Task PublishAsync(T obj) 18 | { 19 | await using var connection = await _connectionFactory.CreateConnectionAsync(); 20 | 21 | await using var channel = await connection.CreateChannelAsync(); 22 | 23 | await QueueDeclareAsync(channel); 24 | 25 | await channel.BasicPublishAsync(exchange: string.Empty, routingKey: typeof(T).Name, body: obj.Bytes()); 26 | } 27 | 28 | public async Task SubscribeAsync(Func action) 29 | { 30 | await using var connection = await _connectionFactory.CreateConnectionAsync(); 31 | 32 | await using var channel = await connection.CreateChannelAsync(); 33 | 34 | await QueueDeclareAsync(channel); 35 | 36 | var consumer = new AsyncEventingBasicConsumer(channel); 37 | 38 | consumer.ReceivedAsync += (_, args) => action(args.Body.ToArray().Object()); 39 | 40 | await channel.BasicConsumeAsync(queue: typeof(T).Name, autoAck: true, consumer: consumer); 41 | 42 | var autoResetEvent = new AutoResetEvent(false); 43 | 44 | Console.CancelKeyPress += (_, args) => { autoResetEvent.Set(); args.Cancel = true; }; 45 | 46 | autoResetEvent.WaitOne(); 47 | } 48 | 49 | private static async Task QueueDeclareAsync(IChannel channel) 50 | { 51 | await channel.QueueDeclareAsync(queue: typeof(T).Name, durable: true, exclusive: false, autoDelete: false); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /source/RabbitMQ/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.RabbitMQ 2 | 3 | ## Connection 4 | 5 | ```cs 6 | public sealed record Connection(string HostName, int Port, string UserName, string Password); 7 | ``` 8 | 9 | ## IQueue 10 | 11 | ```cs 12 | public interface IQueue 13 | { 14 | Task PublishAsync(T obj); 15 | 16 | Task SubscribeAsync(Func action); 17 | } 18 | ``` 19 | 20 | ## Queue 21 | 22 | ```cs 23 | public abstract class Queue : IQueue 24 | { 25 | protected Queue(Connection connection) { } 26 | 27 | public async Task PublishAsync(T obj) { } 28 | 29 | public async Task SubscribeAsync(Func action) { } 30 | } 31 | ``` 32 | 33 | ## Example 34 | 35 | ### Message 36 | 37 | ```cs 38 | public sealed record Product(string Name); 39 | ``` 40 | 41 | ### Queue 42 | 43 | ```cs 44 | public interface IProductQueue : IQueue { } 45 | ``` 46 | 47 | ```cs 48 | public class ProductQueue : Queue, IProductQueue 49 | { 50 | public ProductQueue(Connection connection) : base(connection) { } 51 | } 52 | ``` 53 | 54 | ### Publisher 55 | 56 | ```cs 57 | var product = new Product("Product"); 58 | 59 | IProductQueue productQueue = new ProductQueue(new Connection("localhost", 5672, "admin", "P4ssW0rd!")); 60 | 61 | productQueue.PublishAsync(product).Wait(); 62 | ``` 63 | 64 | ### Subscriber 65 | 66 | ```cs 67 | IProductQueue productQueue = new ProductQueue(new Connection("localhost", 5672, "admin", "P4ssW0rd!")); 68 | 69 | productQueue.SubscribeAsync(product => Handle(product)).Wait(); 70 | ``` 71 | -------------------------------------------------------------------------------- /source/Repositories/DotNetCore.Repositories.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.Repositories 4 | DotNetCore.Repositories 5 | DotNetCore.Repositories 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/Repositories 7 | Repository, GenericRepository, BaseRepository, RepositoryBase, CommandRepository, QueryRepository, CQRS, Command, Query 8 | DotNetCore.Repositories 9 | 10 | 11 | -------------------------------------------------------------------------------- /source/Repositories/ICommandRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | 3 | namespace DotNetCore.Repositories; 4 | 5 | public interface ICommandRepository where T : class 6 | { 7 | void Add(T item); 8 | 9 | Task AddAsync(T item); 10 | 11 | void AddRange(IEnumerable items); 12 | 13 | Task AddRangeAsync(IEnumerable items); 14 | 15 | void Delete(object key); 16 | 17 | void Delete(Expression> where); 18 | 19 | Task DeleteAsync(object key); 20 | 21 | Task DeleteAsync(Expression> where); 22 | 23 | void Update(T item); 24 | 25 | Task UpdateAsync(T item); 26 | 27 | void UpdatePartial(object item); 28 | 29 | Task UpdatePartialAsync(object item); 30 | 31 | void UpdateRange(IEnumerable items); 32 | 33 | Task UpdateRangeAsync(IEnumerable items); 34 | } 35 | -------------------------------------------------------------------------------- /source/Repositories/IQueryRepository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | 3 | namespace DotNetCore.Repositories; 4 | 5 | public interface IQueryRepository where T : class 6 | { 7 | IQueryable Queryable { get; } 8 | 9 | bool Any(); 10 | 11 | bool Any(Expression> where); 12 | 13 | Task AnyAsync(); 14 | 15 | Task AnyAsync(Expression> where); 16 | 17 | long Count(); 18 | 19 | long Count(Expression> where); 20 | 21 | Task CountAsync(); 22 | 23 | Task CountAsync(Expression> where); 24 | 25 | T Get(object key); 26 | 27 | Task GetAsync(object key); 28 | 29 | IEnumerable List(); 30 | 31 | Task> ListAsync(); 32 | } 33 | -------------------------------------------------------------------------------- /source/Repositories/IRepository.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Repositories; 2 | 3 | public interface IRepository : ICommandRepository, IQueryRepository where T : class; 4 | -------------------------------------------------------------------------------- /source/Repositories/Repository.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | 3 | namespace DotNetCore.Repositories; 4 | 5 | public abstract class Repository(ICommandRepository commandRepository, IQueryRepository queryRepository) : IRepository where T : class 6 | { 7 | public IQueryable Queryable => queryRepository.Queryable; 8 | 9 | public void Add(T item) => commandRepository.Add(item); 10 | 11 | public Task AddAsync(T item) => commandRepository.AddAsync(item); 12 | 13 | public void AddRange(IEnumerable items) => commandRepository.AddRange(items); 14 | 15 | public Task AddRangeAsync(IEnumerable items) => commandRepository.AddRangeAsync(items); 16 | 17 | public bool Any() => queryRepository.Any(); 18 | 19 | public bool Any(Expression> where) => queryRepository.Any(where); 20 | 21 | public Task AnyAsync() => queryRepository.AnyAsync(); 22 | 23 | public Task AnyAsync(Expression> where) => queryRepository.AnyAsync(where); 24 | 25 | public long Count() => queryRepository.Count(); 26 | 27 | public long Count(Expression> where) => queryRepository.Count(where); 28 | 29 | public Task CountAsync() => queryRepository.CountAsync(); 30 | 31 | public Task CountAsync(Expression> where) => queryRepository.CountAsync(where); 32 | 33 | public void Delete(object key) => commandRepository.Delete(key); 34 | 35 | public void Delete(Expression> where) => commandRepository.Delete(where); 36 | 37 | public Task DeleteAsync(object key) => commandRepository.DeleteAsync(key); 38 | 39 | public Task DeleteAsync(Expression> where) => commandRepository.DeleteAsync(where); 40 | 41 | public T Get(object key) => queryRepository.Get(key); 42 | 43 | public Task GetAsync(object key) => queryRepository.GetAsync(key); 44 | 45 | public IEnumerable List() => queryRepository.List(); 46 | 47 | public Task> ListAsync() => queryRepository.ListAsync(); 48 | 49 | public void Update(T item) => commandRepository.Update(item); 50 | 51 | public Task UpdateAsync(T item) => commandRepository.UpdateAsync(item); 52 | 53 | public void UpdatePartial(object item) => commandRepository.UpdatePartial(item); 54 | 55 | public Task UpdatePartialAsync(object item) => commandRepository.UpdatePartialAsync(item); 56 | 57 | public void UpdateRange(IEnumerable items) => commandRepository.UpdateRange(items); 58 | 59 | public Task UpdateRangeAsync(IEnumerable items) => commandRepository.UpdateRangeAsync(items); 60 | } 61 | -------------------------------------------------------------------------------- /source/Repositories/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.Repositories 2 | 3 | ## Repository 4 | 5 | ### ICommandRepository 6 | 7 | ```cs 8 | public interface ICommandRepository where T : class 9 | { 10 | void Add(T item); 11 | 12 | Task AddAsync(T item); 13 | 14 | void AddRange(IEnumerable items); 15 | 16 | Task AddRangeAsync(IEnumerable items); 17 | 18 | void Delete(object key); 19 | 20 | void Delete(Expression> where); 21 | 22 | Task DeleteAsync(object key); 23 | 24 | Task DeleteAsync(Expression> where); 25 | 26 | void Update(T item); 27 | 28 | Task UpdateAsync(T item); 29 | 30 | void UpdatePartial(object item); 31 | 32 | Task UpdatePartialAsync(object item); 33 | 34 | void UpdateRange(IEnumerable items); 35 | 36 | Task UpdateRangeAsync(IEnumerable items); 37 | } 38 | ``` 39 | 40 | ### IQueryRepository 41 | 42 | ```cs 43 | public interface IQueryRepository where T : class 44 | { 45 | IQueryable Queryable { get; } 46 | 47 | bool Any(); 48 | 49 | bool Any(Expression> where); 50 | 51 | Task AnyAsync(); 52 | 53 | Task AnyAsync(Expression> where); 54 | 55 | long Count(); 56 | 57 | long Count(Expression> where); 58 | 59 | Task CountAsync(); 60 | 61 | Task CountAsync(Expression> where); 62 | 63 | T Get(object key); 64 | 65 | Task GetAsync(object key); 66 | 67 | IEnumerable List(); 68 | 69 | Task> ListAsync(); 70 | } 71 | ``` 72 | 73 | ### IRepository 74 | 75 | ```cs 76 | public interface IRepository : ICommandRepository, IQueryRepository where T : class { } 77 | ``` 78 | 79 | ### Repository 80 | 81 | ```cs 82 | public abstract class Repository : IRepository where T : class 83 | { 84 | protected Repository(ICommandRepository commandRepository, IQueryRepository queryRepository) { } 85 | 86 | public IQueryable Queryable { get; }; 87 | 88 | public void Add(T item) { } 89 | 90 | public Task AddAsync(T item) { } 91 | 92 | public void AddRange(IEnumerable items) { } 93 | 94 | public Task AddRangeAsync(IEnumerable items) { } 95 | 96 | public bool Any() { } 97 | 98 | public bool Any(Expression> where) { } 99 | 100 | public Task AnyAsync() { } 101 | 102 | public Task AnyAsync(Expression> where) { } 103 | 104 | public long Count() { } 105 | 106 | public long Count(Expression> where) { } 107 | 108 | public Task CountAsync() { } 109 | 110 | public Task CountAsync(Expression> where) { } 111 | 112 | public void Delete(object key) { } 113 | 114 | public void Delete(Expression> where) { } 115 | 116 | public Task DeleteAsync(object key) { } 117 | 118 | public Task DeleteAsync(Expression> where) { } 119 | 120 | public T Get(object key) { } 121 | 122 | public Task GetAsync(object key) { } 123 | 124 | public IEnumerable List() { } 125 | 126 | public Task> ListAsync() { } 127 | 128 | public void Update(T item) { } 129 | 130 | public Task UpdateAsync(T item) { } 131 | 132 | public void UpdatePartial(object item) { } 133 | 134 | public Task UpdatePartialAsync(object item) { } 135 | 136 | public void UpdateRange(IEnumerable items) { } 137 | 138 | public Task UpdateRangeAsync(IEnumerable items) { } 139 | } 140 | ``` 141 | -------------------------------------------------------------------------------- /source/Results/DotNetCore.Results.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.Results 4 | DotNetCore.Results 5 | DotNetCore.Results 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/Results 7 | Result, ResultPattern, Pattern 8 | DotNetCore.Results 9 | 10 | 11 | -------------------------------------------------------------------------------- /source/Results/Result.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | 3 | namespace DotNetCore.Results; 4 | 5 | public record Result(HttpStatusCode Status) 6 | { 7 | public Result(HttpStatusCode status, string message) : this(status) => Message = message; 8 | 9 | public string Message { get; } 10 | 11 | public bool HasMessage => !string.IsNullOrWhiteSpace(Message); 12 | 13 | public Result Convert() => new(Status, Message); 14 | } 15 | 16 | public sealed record Result : Result 17 | { 18 | public Result(HttpStatusCode status) : base(status) { } 19 | 20 | public Result(HttpStatusCode status, T value) : base(status) { Value = value; } 21 | 22 | public Result(HttpStatusCode status, string message) : base(status, message) { } 23 | 24 | public T Value { get; } 25 | 26 | public bool HasValue => Value is not null; 27 | 28 | public Result Convert() => new(Status, Message); 29 | } 30 | -------------------------------------------------------------------------------- /source/Results/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.Results 2 | 3 | ## Result 4 | 5 | ```cs 6 | public record Result(HttpStatusCode Status) 7 | { 8 | public Result(HttpStatusCode status, string message) { } 9 | 10 | public string Message { get; } 11 | 12 | public bool HasMessage { } 13 | 14 | public Result Convert() { } 15 | } 16 | ``` 17 | 18 | ## Result 19 | 20 | ```cs 21 | public sealed record Result : Result 22 | { 23 | public Result(HttpStatusCode status) { } 24 | 25 | public Result(HttpStatusCode status, T value) { } 26 | 27 | public Result(HttpStatusCode status, string message) { } 28 | 29 | public T Value { get; } 30 | 31 | public bool HasValue { } 32 | 33 | public Result Convert() { } 34 | } 35 | ``` 36 | -------------------------------------------------------------------------------- /source/Security/Cryptography/CryptographyService.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography; 2 | using System.Text; 3 | 4 | namespace DotNetCore.Security; 5 | 6 | public class CryptographyService(string key) : ICryptographyService 7 | { 8 | public string Decrypt(string value, string salt) 9 | { 10 | using var algorithm = Algorithm(salt); 11 | 12 | return Encoding.Default.GetString(Transform(Convert.FromBase64String(value), algorithm.CreateDecryptor())); 13 | } 14 | 15 | public string Encrypt(string value, string salt) 16 | { 17 | using var algorithm = Algorithm(salt); 18 | 19 | return Convert.ToBase64String(Transform(Encoding.Default.GetBytes(value), algorithm.CreateEncryptor())); 20 | } 21 | 22 | private static byte[] Transform(byte[] bytes, ICryptoTransform cryptoTransform) 23 | { 24 | using (cryptoTransform) { return cryptoTransform.TransformFinalBlock(bytes, 0, bytes.Length); } 25 | } 26 | 27 | private SymmetricAlgorithm Algorithm(string salt) 28 | { 29 | using var key1 = KeyGenerator.Generate(key, salt); 30 | 31 | var algorithm = Aes.Create(); 32 | 33 | algorithm.Key = key1.GetBytes(algorithm.KeySize / 8); 34 | 35 | algorithm.IV = key1.GetBytes(algorithm.BlockSize / 8); 36 | 37 | return algorithm; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /source/Security/Cryptography/ICryptographyService.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Security; 2 | 3 | public interface ICryptographyService 4 | { 5 | string Decrypt(string value, string salt); 6 | 7 | string Encrypt(string value, string salt); 8 | } 9 | -------------------------------------------------------------------------------- /source/Security/DotNetCore.Security.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.Security 4 | DotNetCore.Security 5 | DotNetCore.Security 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/Security 7 | Security, Cryptography, Hash, JWT 8 | DotNetCore.Security 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /source/Security/Extensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace DotNetCore.Security; 4 | 5 | public static class Extensions 6 | { 7 | public static void AddCryptographyService(this IServiceCollection services, string key) => services.AddSingleton(_ => new CryptographyService(key)); 8 | 9 | public static void AddHashService(this IServiceCollection services) => services.AddSingleton(); 10 | } 11 | -------------------------------------------------------------------------------- /source/Security/Hash/HashService.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Security; 2 | 3 | public class HashService : IHashService 4 | { 5 | public string Create(string value, string salt) 6 | { 7 | using var key = KeyGenerator.Generate(value, salt); 8 | 9 | return Convert.ToBase64String(key.GetBytes(512)); 10 | } 11 | 12 | public bool Validate(string hash, string value, string salt) => hash == Create(value, salt); 13 | } 14 | -------------------------------------------------------------------------------- /source/Security/Hash/IHashService.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Security; 2 | 3 | public interface IHashService 4 | { 5 | string Create(string value, string salt); 6 | 7 | bool Validate(string hash, string value, string salt); 8 | } 9 | -------------------------------------------------------------------------------- /source/Security/KeyGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography; 2 | using System.Text; 3 | 4 | namespace DotNetCore.Security; 5 | 6 | public static class KeyGenerator 7 | { 8 | public static DeriveBytes Generate(string password, string salt) => new Rfc2898DeriveBytes(password, Encoding.Default.GetBytes(salt), 10000, HashAlgorithmName.SHA512); 9 | } 10 | -------------------------------------------------------------------------------- /source/Security/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.Security 2 | 3 | ## Cryptography 4 | 5 | ### ICryptographyService 6 | 7 | ```cs 8 | public interface ICryptographyService 9 | { 10 | string Decrypt(string value, string salt); 11 | 12 | string Encrypt(string value, string salt); 13 | } 14 | ``` 15 | 16 | ### CryptographyService 17 | 18 | ```cs 19 | public class CryptographyService : ICryptographyService 20 | { 21 | public CryptographyService(string key) { } 22 | 23 | public string Decrypt(string value, string salt) { } 24 | 25 | public string Encrypt(string value, string salt) { } 26 | } 27 | ``` 28 | 29 | ## Hash 30 | 31 | ### IHashService 32 | 33 | ```cs 34 | public interface IHashService 35 | { 36 | string Create(string value, string salt); 37 | 38 | bool Validate(string hash, string value, string salt); 39 | } 40 | ``` 41 | 42 | ### HashService 43 | 44 | ```cs 45 | public class HashService : IHashService 46 | { 47 | public string Create(string value, string salt) { } 48 | 49 | public bool Validate(string hash, string value, string salt) { } 50 | } 51 | ``` 52 | 53 | ## Extensions 54 | 55 | ```cs 56 | public static class Extensions 57 | { 58 | public static void AddCryptographyService(this IServiceCollection services, string key) { } 59 | 60 | public static void AddHashService(this IServiceCollection services) { } 61 | } 62 | ``` 63 | -------------------------------------------------------------------------------- /source/Services/Csv/CsvService.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace DotNetCore.Services; 4 | 5 | public class CsvService : ICsvService 6 | { 7 | public async Task> ReadAsync(string path, char separator = ',') where T : new() 8 | { 9 | if (!File.Exists(path)) return []; 10 | 11 | var lines = await File.ReadAllLinesAsync(path); 12 | 13 | if (lines.Length < 2) return []; 14 | 15 | var headers = lines.First().Split(separator); 16 | 17 | if (!headers.Any()) return []; 18 | 19 | var items = new List(); 20 | 21 | foreach (var line in lines.Skip(1)) 22 | { 23 | var values = line.Split(separator); 24 | 25 | var item = new T(); 26 | 27 | for (var i = 0; i < headers.Length; i++) 28 | { 29 | var property = item.GetType().GetProperty(headers[i]); 30 | 31 | if (property is null) continue; 32 | 33 | var type = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType; 34 | 35 | var value = Convert.ChangeType(values[i], type, CultureInfo.InvariantCulture); 36 | 37 | property.SetValue(item, value); 38 | } 39 | 40 | items.Add(item); 41 | } 42 | 43 | return items; 44 | } 45 | 46 | public async Task WriteAsync(IEnumerable items, string path, char separator = ',') 47 | { 48 | using var stream = await WriteAsync(items); 49 | 50 | await File.WriteAllBytesAsync(path, stream.ToArray()); 51 | } 52 | 53 | public async Task WriteAsync(IEnumerable items, char separator = ',') 54 | { 55 | var enumerable = items.ToList(); 56 | 57 | if (!enumerable.Any()) return new MemoryStream(); 58 | 59 | var properties = typeof(T).GetProperties(); 60 | 61 | var memoryStream = new MemoryStream(); 62 | 63 | await using var streamWriter = new StreamWriter(memoryStream); 64 | 65 | await streamWriter.WriteLineAsync(string.Join(separator, properties.Select(property => property.Name))); 66 | 67 | enumerable.ForEach(item => streamWriter.WriteLine(string.Join(separator, properties.Select(property => property.GetValue(item))))); 68 | 69 | await streamWriter.FlushAsync(); 70 | 71 | await memoryStream.FlushAsync(); 72 | 73 | memoryStream.Position = 0; 74 | 75 | return memoryStream; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /source/Services/Csv/ICsvService.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Services; 2 | 3 | public interface ICsvService 4 | { 5 | Task> ReadAsync(string path, char separator = ',') where T : new(); 6 | 7 | Task WriteAsync(IEnumerable items, string path, char separator = ','); 8 | 9 | Task WriteAsync(IEnumerable items, char separator = ','); 10 | } 11 | -------------------------------------------------------------------------------- /source/Services/DotNetCore.Services.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.Services 4 | DotNetCore.Services 5 | DotNetCore.Services 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/Services 7 | Services 8 | DotNetCore.Services 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /source/Services/Extensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.Localization; 3 | 4 | namespace DotNetCore.Services; 5 | 6 | public static class Extensions 7 | { 8 | public static void AddCsvService(this IServiceCollection services) => services.AddSingleton(); 9 | 10 | public static void AddFileCache(this IServiceCollection services) => services.AddSingleton(); 11 | 12 | public static void AddJsonStringLocalizer(this IServiceCollection services) => services.AddSingleton(); 13 | } 14 | -------------------------------------------------------------------------------- /source/Services/FileCache/FileCache.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json; 2 | using System.Text.Json.Serialization; 3 | 4 | namespace DotNetCore.Services; 5 | 6 | public sealed class FileCache : IFileCache 7 | { 8 | private readonly Lock _lock = new(); 9 | 10 | public void Clear(string file) => File.Delete(file); 11 | 12 | public T Set(string file, TimeSpan expiration, T value) 13 | { 14 | lock (_lock) 15 | { 16 | var content = new FileCacheContent(value, DateTime.UtcNow.Add(expiration)); 17 | 18 | var options = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; 19 | 20 | File.WriteAllText(file, JsonSerializer.Serialize(content, options)); 21 | 22 | return value; 23 | } 24 | } 25 | 26 | public bool TryGetValue(string file, out T value) 27 | { 28 | lock (_lock) 29 | { 30 | if (!File.Exists(file)) 31 | { 32 | value = default; 33 | 34 | return false; 35 | } 36 | 37 | var content = JsonSerializer.Deserialize>(File.ReadAllText(file)); 38 | 39 | if (content is null) 40 | { 41 | value = default; 42 | 43 | return false; 44 | } 45 | 46 | if (DateTime.UtcNow >= content.Expiration) 47 | { 48 | File.Delete(file); 49 | 50 | value = default; 51 | 52 | return false; 53 | } 54 | 55 | value = content.Value; 56 | 57 | return true; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /source/Services/FileCache/FileCacheContent.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Services; 2 | 3 | public sealed record FileCacheContent(T Value, DateTime Expiration); 4 | -------------------------------------------------------------------------------- /source/Services/FileCache/IFileCache.cs: -------------------------------------------------------------------------------- 1 | namespace DotNetCore.Services; 2 | 3 | public interface IFileCache 4 | { 5 | void Clear(string file); 6 | 7 | T Set(string file, TimeSpan expiration, T value); 8 | 9 | bool TryGetValue(string file, out T value); 10 | } 11 | -------------------------------------------------------------------------------- /source/Services/Http/HttpOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http.Headers; 2 | 3 | namespace DotNetCore.Services; 4 | 5 | public sealed record HttpOptions 6 | { 7 | public string BaseAddress { get; set; } 8 | 9 | public AuthenticationHeaderValue Authentication { get; set; } 10 | 11 | public int TimeoutSeconds { get; set; } = 5; 12 | 13 | public int RetryCount { get; set; } 14 | 15 | public int RetrySeconds { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /source/Services/Http/HttpService.cs: -------------------------------------------------------------------------------- 1 | using Polly; 2 | using Polly.Retry; 3 | using System.Net; 4 | using System.Net.Http.Headers; 5 | using System.Net.Http.Json; 6 | using System.Net.Mime; 7 | 8 | namespace DotNetCore.Services; 9 | 10 | public abstract class HttpService : IHttpService 11 | { 12 | private readonly HttpClient _client; 13 | 14 | private readonly AsyncRetryPolicy _retryPolicy; 15 | 16 | protected HttpService(HttpOptions options) 17 | { 18 | _retryPolicy = Policy.Handle().OrResult(response => !response.IsSuccessStatusCode).WaitAndRetryAsync(options.RetryCount, _ => TimeSpan.FromSeconds(options.RetrySeconds)); 19 | 20 | _client = new HttpClient { Timeout = TimeSpan.FromSeconds(options.TimeoutSeconds) }; 21 | 22 | _client.DefaultRequestHeaders.Clear(); 23 | 24 | _client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(nameof(HttpService), string.Empty)); 25 | 26 | _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json)); 27 | 28 | if (options.BaseAddress is not null) _client.BaseAddress = new Uri(options.BaseAddress); 29 | 30 | if (options.Authentication is not null) _client.DefaultRequestHeaders.Authorization = options.Authentication; 31 | } 32 | 33 | public async Task DeleteAsync(string uri) 34 | { 35 | return (await _retryPolicy.ExecuteAsync(() => _client.DeleteAsync(uri))).StatusCode; 36 | } 37 | 38 | public async Task<(HttpStatusCode, TResponse)> GetAsync(string uri) 39 | { 40 | var response = await _retryPolicy.ExecuteAsync(() => _client.GetAsync(uri)); 41 | 42 | return (response.StatusCode, await response.Content.ReadFromJsonAsync()); 43 | } 44 | 45 | public async Task PatchAsync(string uri, object value) 46 | { 47 | return (await _retryPolicy.ExecuteAsync(() => _client.PatchAsJsonAsync(uri, value))).StatusCode; 48 | } 49 | 50 | public async Task PostAsync(string uri, object value) 51 | { 52 | return (await _retryPolicy.ExecuteAsync(() => _client.PostAsJsonAsync(uri, value))).StatusCode; 53 | } 54 | 55 | public async Task<(HttpStatusCode, TResponse)> PostAsync(string uri, object value) 56 | { 57 | var response = await _retryPolicy.ExecuteAsync(() => _client.PostAsJsonAsync(uri, value)); 58 | 59 | return (response.StatusCode, await response.Content.ReadFromJsonAsync()); 60 | } 61 | 62 | public async Task PutAsync(string uri, object value) 63 | { 64 | return (await _retryPolicy.ExecuteAsync(() => _client.PutAsJsonAsync(uri, value))).StatusCode; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /source/Services/Http/IHttpService.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | 3 | namespace DotNetCore.Services; 4 | 5 | public interface IHttpService 6 | { 7 | Task DeleteAsync(string uri); 8 | 9 | Task<(HttpStatusCode, TResponse)> GetAsync(string uri); 10 | 11 | Task PatchAsync(string uri, object value); 12 | 13 | Task PostAsync(string uri, object value); 14 | 15 | Task<(HttpStatusCode, TResponse)> PostAsync(string uri, object value); 16 | 17 | Task PutAsync(string uri, object value); 18 | } 19 | -------------------------------------------------------------------------------- /source/Services/JsonStringLocalizer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Localization; 2 | using System.Collections.Concurrent; 3 | using System.Globalization; 4 | using System.Text.Json; 5 | 6 | namespace DotNetCore.Services; 7 | 8 | public class JsonStringLocalizer : IStringLocalizer 9 | { 10 | private static ConcurrentDictionary> Strings => JsonSerializer.Deserialize>>(File.ReadAllText("AppStrings.json")); 11 | 12 | public LocalizedString this[string name] => Get(name); 13 | 14 | public LocalizedString this[string name, params object[] arguments] => Get(name, arguments); 15 | 16 | public IEnumerable GetAllStrings(bool includeParentCultures) => Strings.Keys.Select(key => new LocalizedString(key, key)); 17 | 18 | private static LocalizedString Get(string name, params object[] arguments) 19 | { 20 | var localizedString = new LocalizedString(name, name, true, nameof(JsonStringLocalizer)); 21 | 22 | return string.IsNullOrWhiteSpace(name) || !Strings.TryGetValue(name, out var dictionary) 23 | ? localizedString 24 | : !dictionary.TryGetValue(CultureInfo.CurrentCulture.Name, out var value) 25 | ? localizedString 26 | : new LocalizedString(name, string.Format(value, arguments), false, nameof(JsonStringLocalizer)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /source/Services/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.Services 2 | 3 | ## CsvService 4 | 5 | ### ICsvService 6 | 7 | ```cs 8 | public interface ICsvService 9 | { 10 | Task> ReadAsync(string path, char separator = ',') where T : new(); 11 | 12 | Task WriteAsync(IEnumerable items, string path, char separator = ','); 13 | 14 | Task WriteAsync(IEnumerable items, char separator = ','); 15 | } 16 | ``` 17 | 18 | ### CsvService 19 | 20 | ```cs 21 | public class CsvService : ICsvService 22 | { 23 | public async Task> ReadAsync(string path, char separator = ',') where T : new() { } 24 | 25 | public async Task WriteAsync(IEnumerable items, string path, char separator = ',') { } 26 | 27 | public async Task WriteAsync(IEnumerable items, char separator = ',') { } 28 | } 29 | ``` 30 | 31 | ### Example 32 | 33 | ```cs 34 | public sealed record Person 35 | { 36 | public int Id { get; set; } 37 | 38 | public string Name { get; set; } 39 | } 40 | ``` 41 | 42 | ```cs 43 | public static void Main() 44 | { 45 | var people = new List(); 46 | 47 | var stream = WriteAsync(people).Result; 48 | 49 | WriteAsync(people, "People.csv").Wait(); 50 | 51 | people = ReadAsync("People.csv").Result; 52 | } 53 | ``` 54 | 55 | ## FileCache 56 | 57 | ### IFileCache 58 | 59 | ```cs 60 | public interface IFileCache 61 | { 62 | void Clear(string file); 63 | 64 | T Set(string file, TimeSpan expiration, T value); 65 | 66 | bool TryGetValue(string file, out T value); 67 | } 68 | ``` 69 | 70 | ### FileCache 71 | 72 | ```cs 73 | public sealed class FileCache : IFileCache 74 | { 75 | public void Clear(string file) { } 76 | 77 | public T Set(string file, TimeSpan expiration, T value) { } 78 | 79 | public bool TryGetValue(string file, out T value) { } 80 | } 81 | ``` 82 | 83 | ## Http 84 | 85 | ### HttpOptions 86 | 87 | ```cs 88 | public sealed record HttpOptions 89 | { 90 | public string BaseAddress { get; set; } 91 | 92 | public AuthenticationHeaderValue Authentication { get; set; } 93 | 94 | public int TimeoutSeconds { get; set; } = 5; 95 | 96 | public int RetryCount { get; set; } 97 | 98 | public int RetrySeconds { get; set; } 99 | } 100 | ``` 101 | 102 | ### IHttpService 103 | 104 | ```cs 105 | public interface IHttpService 106 | { 107 | Task DeleteAsync(string uri); 108 | 109 | Task<(HttpStatusCode, TResponse)> GetAsync(string uri); 110 | 111 | Task PatchAsync(string uri, object value); 112 | 113 | Task PostAsync(string uri, object value); 114 | 115 | Task<(HttpStatusCode, TResponse)> PostAsync(string uri, object value); 116 | 117 | Task PutAsync(string uri, object value); 118 | } 119 | ``` 120 | 121 | ### HttpService 122 | 123 | ```cs 124 | public abstract class HttpService : IHttpService 125 | { 126 | public async Task DeleteAsync(string uri) { } 127 | 128 | public async Task<(HttpStatusCode, TResponse)> GetAsync(string uri) { } 129 | 130 | public async Task PatchAsync(string uri, object value) { } 131 | 132 | public async Task PostAsync(string uri, object value) { } 133 | 134 | public async Task<(HttpStatusCode, TResponse)> PostAsync(string uri, object value) { } 135 | 136 | public async Task PutAsync(string uri, object value) { } 137 | } 138 | ``` 139 | 140 | ### Example 141 | 142 | ```cs 143 | public interface ITestHttpService : IHttpService { } 144 | ``` 145 | 146 | ```cs 147 | public sealed record TestHttpService(HttpOptions options) : HttpService(options), ITestHttpService; 148 | ``` 149 | 150 | ```cs 151 | public sealed record Todo(int Id, string Title); 152 | ``` 153 | 154 | ```cs 155 | public class Program 156 | { 157 | public static void Main() 158 | { 159 | var baseAddress = "https://jsonplaceholder.typicode.com"; 160 | 161 | var options = new HttpOptions { BaseAddress = baseAddress }; 162 | 163 | ITestHttpService httpService = new TestHttpService(options); 164 | 165 | var services = new ServiceCollection(); 166 | 167 | services.AddScoped(provider => httpService); 168 | 169 | httpService = services.BuildServiceProvider().GetRequiredService(); 170 | 171 | var deleteError = httpService.DeleteAsync("todo/1").Result; 172 | 173 | var deleteSuccess = httpService.DeleteAsync("todos/1").Result; 174 | 175 | var listError = httpService.GetAsync>("todo").Result; 176 | 177 | var listSuccess = httpService.GetAsync>("todos").Result; 178 | 179 | var getError = httpService.GetAsync("todo/1").Result; 180 | 181 | var getSuccess = httpService.GetAsync("todos/1").Result; 182 | 183 | var postError = httpService.PostAsync("todo", default).Result; 184 | 185 | var postSuccess = httpService.PostAsync("todos", new { Title = "Title" }).Result; 186 | 187 | var postResultError = httpService.PostAsync("todo", default).Result; 188 | 189 | var postResultSuccess = httpService.PostAsync("todos", new { Title = "Title" }).Result; 190 | 191 | var putError = httpService.PutAsync("todo/1", default).Result; 192 | 193 | var putSuccess = httpService.PutAsync("todos/1", new { Title = "Title" }).Result; 194 | } 195 | } 196 | ``` 197 | 198 | ## JsonStringLocalizer 199 | 200 | ```cs 201 | public class JsonStringLocalizer : IStringLocalizer 202 | { 203 | public JsonStringLocalizer(string path) { } 204 | } 205 | ``` 206 | 207 | ## Extensions 208 | 209 | ```cs 210 | public static class Extensions 211 | { 212 | public static void AddCsvService(this IServiceCollection services) { } 213 | 214 | public static void AddFileCache(this IServiceCollection services) { } 215 | 216 | public static void AddJsonStringLocalizer(this IServiceCollection services) { } 217 | } 218 | ``` 219 | -------------------------------------------------------------------------------- /source/Validation/DotNetCore.Validation.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | DotNetCore.Validation 4 | DotNetCore.Validation 5 | DotNetCore.Validation 6 | https://github.com/rafaelfgx/DotNetCore/tree/main/source/Validation 7 | Validation, Validator 8 | DotNetCore.Validation 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /source/Validation/Extensions.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | 3 | namespace DotNetCore.Validation; 4 | 5 | public static class Extensions 6 | { 7 | public static (bool, string) Validation(this IValidator validator, T instance) 8 | { 9 | if (instance is null) return (false, default); 10 | 11 | var result = validator.Validate(instance); 12 | 13 | return (result.IsValid, result.ToString()); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /source/Validation/readme.md: -------------------------------------------------------------------------------- 1 | # DotNetCore.Validation 2 | 3 | ## Extensions 4 | 5 | ```cs 6 | public static class Extensions 7 | { 8 | public static (bool, string) Validation(this IValidator validator, T instance) { } 9 | } 10 | ``` 11 | -------------------------------------------------------------------------------- /source/global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "9.0.301", 4 | "rollForward": "latestMajor" 5 | } 6 | } 7 | --------------------------------------------------------------------------------