From e36f3f64749065a9e0b2dc71b1c41c1e740a6cfa Mon Sep 17 00:00:00 2001 From: ShadyNagy Date: Fri, 22 Mar 2024 00:30:39 +0200 Subject: [PATCH] start. --- .editorconfig | 143 ++++++++++++++++++ .github/workflows/build.yml | 25 +++ .github/workflows/nuget-publish.yml | 34 +++++ Directory.Packages.props | 62 ++++++++ DynamicDiToolkit.nuspec | 33 ++++ DynamicDiToolkit.sln | 43 ++++++ README.md | 11 +- icon.png | Bin 0 -> 44546 bytes nuget.config | 27 ++++ src/DynamicDiToolkit/DynamicDiToolkit.csproj | 20 +++ .../Extensions/ServiceCollectionExtensions.cs | 28 ++++ .../Interfaces/IAggregateRoot.cs | 5 + .../IArdalisSpecificationRepositoryFactory.cs | 12 ++ .../Interfaces/IRepository.cs | 6 + .../ArdalisSpecificationRepositoryFactory.cs | 72 +++++++++ 15 files changed, 520 insertions(+), 1 deletion(-) create mode 100644 .editorconfig create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/nuget-publish.yml create mode 100644 Directory.Packages.props create mode 100644 DynamicDiToolkit.nuspec create mode 100644 DynamicDiToolkit.sln create mode 100644 icon.png create mode 100644 nuget.config create mode 100644 src/DynamicDiToolkit/DynamicDiToolkit.csproj create mode 100644 src/DynamicDiToolkit/Extensions/ServiceCollectionExtensions.cs create mode 100644 src/DynamicDiToolkit/Interfaces/IAggregateRoot.cs create mode 100644 src/DynamicDiToolkit/Interfaces/IArdalisSpecificationRepositoryFactory.cs create mode 100644 src/DynamicDiToolkit/Interfaces/IRepository.cs create mode 100644 src/DynamicDiToolkit/Services/ArdalisSpecificationRepositoryFactory.cs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..bd36349 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,143 @@ +# To learn more about .editorconfig see https://aka.ms/editorconfigdocs +############################### +# Core EditorConfig Options # +############################### +# All files +[*] +indent_style =tab +# Code files +[*.{cs,csx,vb,vbx}] +#indent_size = 2 +insert_final_newline = true +charset = utf-8-bom +############################### +# .NET Coding Conventions # +############################### +[*.{cs,vb}] +# Organize usings +dotnet_sort_system_directives_first = true +# this. preferences +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_property = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_event = false:silent +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent +dotnet_style_readonly_field = true:suggestion +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +############################### +# Naming Conventions # +############################### +# Style Definitions +dotnet_naming_style.pascal_case_style.capitalization = pascal_case +# Use PascalCase for constant fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.applicable_accessibilities = * +dotnet_naming_symbols.constant_fields.required_modifiers = const +# Instance fields are camelCase and start with _ +dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields +dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style + +dotnet_naming_symbols.instance_fields.applicable_kinds = field + +dotnet_naming_style.instance_field_style.capitalization = camel_case +dotnet_naming_style.instance_field_style.required_prefix = _ +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 2 +indent_size = 2 +end_of_line = crlf +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +############################### +# C# Coding Conventions # +############################### +[*.cs] +# var preferences +csharp_style_var_for_built_in_types = true:silent +csharp_style_var_when_type_is_apparent = true:silent +csharp_style_var_elsewhere = true:silent +# Expression-bodied members +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_accessors = true:silent +# Pattern matching preferences +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +# Null-checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion +# Modifier preferences +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion +# Expression-level preferences +csharp_prefer_braces = true:silent +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +# Namespaces +csharp_style_namespace_declarations = file_scoped:warning +############################### +# C# Formatting Rules # +############################### +# New line preferences +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true +# Indentation preferences +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left +# Space preferences +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +# Wrapping preferences +csharp_preserve_single_line_statements = true +csharp_preserve_single_line_blocks = true +csharp_using_directive_placement = outside_namespace:silent +csharp_prefer_simple_using_statement = true:suggestion +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +############################### +# VB Coding Conventions # +############################### +[*.vb] +# Modifier preferences +visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..705065f --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,25 @@ +name: .NET Core + +on: + push: + branches: + - main + paths: + - 'src/DynamicDiToolkit/**' + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Setup .NET Core + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '7.x' + - name: Install dependencies + run: dotnet restore + - name: Build + run: dotnet build --configuration Release --no-restore + \ No newline at end of file diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml new file mode 100644 index 0000000..03a193d --- /dev/null +++ b/.github/workflows/nuget-publish.yml @@ -0,0 +1,34 @@ +name: Publish DynamicDiToolkit to NuGet + +on: + push: + branches: + - main # Your default release branch + paths: + - 'src/DynamicDiToolkit/**' + +jobs: + publish: + name: Build and Publish + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + + # Required for a specific dotnet version that doesn't come with ubuntu-latest / windows-latest + - name: Setup dotnet + uses: actions/setup-dotnet@v3 + with: + dotnet-version: '7.0.x' + + # Restore + - name: Dotnet restore + run: dotnet restore src/DynamicDiToolkit/DynamicDiToolkit.csproj + + # Publish + - name: Create the package + run: dotnet pack -c Release -o . src/DynamicDiToolkit/DynamicDiToolkit.csproj + + - name: Publish to nuget.org + env: + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + run: nuget push DynamicDiToolkit.*.nupkg -src https://api.nuget.org/v3/index.json ${{secrets.NUGET_API_KEY}} diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 0000000..865dfcc --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,62 @@ + + + true + true + + + + + + + + runtime; build; native; contentfiles; analyzers + all + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + \ No newline at end of file diff --git a/DynamicDiToolkit.nuspec b/DynamicDiToolkit.nuspec new file mode 100644 index 0000000..2aff669 --- /dev/null +++ b/DynamicDiToolkit.nuspec @@ -0,0 +1,33 @@ + + + + DynamicDiToolkit + Dynamic DI Toolkit + 1.0.0 + ShadyNagy + + Dynamic DI Toolkit Package + + + + + + + + + en-US + MIT + https://github.com/ShadyNagy/DynamicDiToolkit + + DynamicDiToolkit Package. + DynamicDiToolkit, DI, Ardalis Specification, dependency injection, service, services + icon.png + Copyright 2024 (c) ShadyNagy. All rights reserved. + README.md + + + + + + + \ No newline at end of file diff --git a/DynamicDiToolkit.sln b/DynamicDiToolkit.sln new file mode 100644 index 0000000..6b777df --- /dev/null +++ b/DynamicDiToolkit.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33815.320 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1A59296A-18CF-4272-A9CB-04CCCD18F460}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{C1B38C9A-65EC-42E7-90A9-5B6EA55C6B4A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FCF0E238-EED0-482A-9ACC-650693578B59}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + .gitignore = .gitignore + .github\workflows\build.yml = .github\workflows\build.yml + Directory.Packages.props = Directory.Packages.props + DynamicDiToolkit.nuspec = DynamicDiToolkit.nuspec + .github\workflows\nuget-publish.yml = .github\workflows\nuget-publish.yml + README.md = README.md + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynamicDiToolkit", "src\DynamicDiToolkit\DynamicDiToolkit.csproj", "{072876FE-DDD8-43EB-8FD4-C11B840DB63F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {072876FE-DDD8-43EB-8FD4-C11B840DB63F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {072876FE-DDD8-43EB-8FD4-C11B840DB63F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {072876FE-DDD8-43EB-8FD4-C11B840DB63F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {072876FE-DDD8-43EB-8FD4-C11B840DB63F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {072876FE-DDD8-43EB-8FD4-C11B840DB63F} = {1A59296A-18CF-4272-A9CB-04CCCD18F460} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8F8D7AF9-01CD-4A86-88AF-2770F7FBC902} + EndGlobalSection +EndGlobal diff --git a/README.md b/README.md index 658a5bc..7772336 100644 --- a/README.md +++ b/README.md @@ -1 +1,10 @@ -# DynamicDiToolkit \ No newline at end of file +[![publish to nuget](https://github.com/ShadyNagy/DynamicDiToolkit/actions/workflows/nuget-publish.yml/badge.svg)](https://github.com/ShadyNagy/DynamicDiToolkit/actions/workflows/nuget-publish.yml) +[![DynamicDiToolkit on NuGet](https://img.shields.io/nuget/v/DynamicDiToolkit?label=DynamicDiToolkit)](https://www.nuget.org/packages/DynamicDiToolkit/) +[![NuGet](https://img.shields.io/nuget/dt/DynamicDiToolkit)](https://www.nuget.org/packages/DynamicDiToolkit) +[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/ShadyNagy/DynamicDiToolkit/blob/main/LICENSE) +[![paypal](https://img.shields.io/badge/PayPal-tip%20me-green.svg?logo=paypal)](https://www.paypal.me/shadynagy) +[![Visit My Website](https://img.shields.io/badge/Visit-My%20Website-blue?logo=internetexplorer)](https://ShadyNagy.com) + + +# Dynamic DI Toolkit + diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0bc843fa1ebe6adf2fbd81f6a5bbec230d7614e9 GIT binary patch literal 44546 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

ha;hQx6<-K&bp(|(?K`2LLq{il@>s5ERRn5&% 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


M^(Ak2c8efzxWV zGYcFcs{;9eE45hf=LsR}QKb{88M4fiYBg1EH;4*)ggptwK;^Y&`SOm70ngPh+&k2I z>jR0hE`tXG5mHnY(u%s}$y1K-DV^Lu$T$(_%-=N-ssgX@24BmuEyCi`ALrN<4`q^a z{x)6LOHQ9|Z5i+q#LNRnEh7Iqo$*{{Xz2O`gRq=_%jQ>yDeo^QzAlwc2q+OqNVS-< zSRA?7S#>F4`_8cONQ}72(v9Nyy7|btR`Eob^mE{Wk~dgNc;Z^a6bD8abj8&2V%Y_3 G!v6#7^1mwp literal 0 HcmV?d00001 diff --git a/nuget.config b/nuget.config new file mode 100644 index 0000000..d98c142 --- /dev/null +++ b/nuget.config @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/DynamicDiToolkit/DynamicDiToolkit.csproj b/src/DynamicDiToolkit/DynamicDiToolkit.csproj new file mode 100644 index 0000000..59fdd1f --- /dev/null +++ b/src/DynamicDiToolkit/DynamicDiToolkit.csproj @@ -0,0 +1,20 @@ + + + + net7.0 + ../../DynamicDiToolkit.nuspec + 10.0 + enable + true + + + + + + + + + + + + diff --git a/src/DynamicDiToolkit/Extensions/ServiceCollectionExtensions.cs b/src/DynamicDiToolkit/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 0000000..76b4574 --- /dev/null +++ b/src/DynamicDiToolkit/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,28 @@ +using DynamicDiToolkit.Services; +using DynamicDiToolkit.Interfaces; +using Microsoft.Extensions.DependencyInjection; + +namespace DynamicDiToolkit.Extensions; +public static class ServiceCollectionExtensions +{ + public static IServiceCollection AddSingletonArdalisSpecificationRepositoryFactoryServices(this IServiceCollection services) + { + services.AddSingleton(); + + return services; + } + + public static IServiceCollection AddScopedArdalisSpecificationRepositoryFactoryServices(this IServiceCollection services) + { + services.AddScoped(); + + return services; + } + + public static IServiceCollection AddTransientArdalisSpecificationRepositoryFactoryServices(this IServiceCollection services) + { + services.AddTransient(); + + return services; + } +} diff --git a/src/DynamicDiToolkit/Interfaces/IAggregateRoot.cs b/src/DynamicDiToolkit/Interfaces/IAggregateRoot.cs new file mode 100644 index 0000000..480c107 --- /dev/null +++ b/src/DynamicDiToolkit/Interfaces/IAggregateRoot.cs @@ -0,0 +1,5 @@ +namespace DynamicDiToolkit.Interfaces; + +public interface IAggregateRoot +{ +} diff --git a/src/DynamicDiToolkit/Interfaces/IArdalisSpecificationRepositoryFactory.cs b/src/DynamicDiToolkit/Interfaces/IArdalisSpecificationRepositoryFactory.cs new file mode 100644 index 0000000..f34c702 --- /dev/null +++ b/src/DynamicDiToolkit/Interfaces/IArdalisSpecificationRepositoryFactory.cs @@ -0,0 +1,12 @@ +using System; +using Ardalis.Specification; + +namespace DynamicDiToolkit.Interfaces; + +public interface IArdalisSpecificationRepositoryFactory +{ + IRepositoryBase GetRepository() where T : class; + IRepositoryBase GetRepository(string className); + IRepositoryBase GetRepository(string entityName, string entitiesAssembly); + IRepositoryBase GetRepository(Type type); +} diff --git a/src/DynamicDiToolkit/Interfaces/IRepository.cs b/src/DynamicDiToolkit/Interfaces/IRepository.cs new file mode 100644 index 0000000..94b835d --- /dev/null +++ b/src/DynamicDiToolkit/Interfaces/IRepository.cs @@ -0,0 +1,6 @@ +using Ardalis.Specification; + +namespace DynamicDiToolkit.Interfaces; +public interface IRepository : IRepositoryBase where T : class +{ +} diff --git a/src/DynamicDiToolkit/Services/ArdalisSpecificationRepositoryFactory.cs b/src/DynamicDiToolkit/Services/ArdalisSpecificationRepositoryFactory.cs new file mode 100644 index 0000000..dd0382e --- /dev/null +++ b/src/DynamicDiToolkit/Services/ArdalisSpecificationRepositoryFactory.cs @@ -0,0 +1,72 @@ +using System; +using System.Linq; +using Ardalis.Specification; +using DynamicDiToolkit.Interfaces; + +namespace DynamicDiToolkit.Services; + +public class ArdalisSpecificationRepositoryFactory : IArdalisSpecificationRepositoryFactory +{ + private readonly IServiceProvider _serviceProvider; + + public ArdalisSpecificationRepositoryFactory(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public IRepositoryBase GetRepository() where T : class + { + var serviceType = typeof(IRepositoryBase); + return (IRepositoryBase)_serviceProvider.GetService(serviceType)! + ?? throw new InvalidOperationException($"Service for type {typeof(T).Name} not found."); + } + + public IRepositoryBase GetRepository(string entityName) + { + var entityType = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(assembly => assembly.GetTypes()) + .FirstOrDefault(type => type.Name.Equals(entityName, StringComparison.OrdinalIgnoreCase)); + + return GetRepositoryInternally(entityType, entityName); + } + + public IRepositoryBase GetRepository(string entityName, string entitiesAssembly) + { + var assembly = AppDomain.CurrentDomain.GetAssemblies() + .FirstOrDefault(a => a.GetName().Name == entitiesAssembly); + var entityType = assembly?.GetTypes() + .FirstOrDefault(t => t.Name.Equals(entityName, StringComparison.OrdinalIgnoreCase)); + + return GetRepositoryInternally(entityType, entityName); + } + + public IRepositoryBase GetRepository(Type type) + { + var repoType = typeof(IRepositoryBase<>).MakeGenericType(type); + var service = _serviceProvider.GetService(repoType); + if (service == null) + { + throw new InvalidOperationException($"Service for type {type.Name} not found."); + } + + return (IRepositoryBase)service; + } + + private IRepositoryBase GetRepositoryInternally(Type? entityType, string entityName) + { + if (entityType == null) + { + throw new InvalidOperationException($"Entity type {entityName} not found."); + } + + var repositoryGenericType = typeof(IRepositoryBase<>).MakeGenericType(entityType); + var repository = _serviceProvider.GetService(repositoryGenericType); + + if (repository == null) + { + throw new InvalidOperationException($"Repository for entity type {entityName} not found."); + } + + return (IRepositoryBase)repository; + } +}