diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..46b858b
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,569 @@
+# https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/language-rules
+
+[*.{cs,vb}]
+tab_width = 4
+indent_size = 4
+end_of_line = crlf
+
+dotnet_diagnostic.ide0001.severity = warning
+dotnet_diagnostic.ide0002.severity = warning
+
+# IDE0003 and IDE0009
+dotnet_diagnostic.sa0001.severity = none
+dotnet_diagnostic.ide0003.severity = warning
+dotnet_diagnostic.ide0009.severity = warning
+dotnet_style_qualification_for_field = false:warning
+dotnet_style_qualification_for_property = false:warning
+dotnet_style_qualification_for_method = false:warning
+dotnet_style_qualification_for_event = false:warning
+
+dotnet_diagnostic.SA1010.severity = none
+
+dotnet_diagnostic.ide0004.severity = warning
+dotnet_diagnostic.ide0005.severity = warning
+
+# IDE0007 and IDE0008
+dotnet_diagnostic.ide0007.severity = warning
+dotnet_diagnostic.ide0008.severity = warning
+csharp_style_var_when_type_is_apparent = true:warning
+csharp_style_var_for_built_in_types = false:silent
+csharp_style_var_elsewhere = false:silent
+
+# IDE0010
+dotnet_diagnostic.ide0010.severity = suggestion
+
+# IDE0011
+dotnet_diagnostic.ide0011.severity = warning
+csharp_prefer_braces = when_multiline:warning
+
+# IDE0016
+dotnet_diagnostic.ide0016.severity = warning
+csharp_style_throw_expression = true:warning
+
+# IDE0017
+dotnet_diagnostic.ide0017.severity = suggestion
+dotnet_style_object_initializer = true:suggestion
+
+# IDE0018
+dotnet_diagnostic.ide0018.severity = suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+
+# IDE0019
+dotnet_diagnostic.ide0019.severity = warning
+csharp_style_pattern_matching_over_as_with_null_check = true:warning
+
+# IDE0020 and IDE0038
+dotnet_diagnostic.ide0020.severity = warning
+dotnet_diagnostic.ide0038.severity = warning
+csharp_style_pattern_matching_over_is_with_cast_check = true:warning
+
+# IDE0021
+dotnet_diagnostic.ide0021.severity = warning
+csharp_style_expression_bodied_constructors = false:warning
+
+# IDE0022
+dotnet_diagnostic.ide0022.severity = suggestion
+csharp_style_expression_bodied_methods = false:suggestion
+
+# IDE0023 and IDE0024
+dotnet_diagnostic.ide0023.severity = suggestion
+dotnet_diagnostic.ide0024.severity = suggestion
+csharp_style_expression_bodied_operators = when_on_single_line:suggestion
+
+# IDE0025
+dotnet_diagnostic.ide0025.severity = warning
+csharp_style_expression_bodied_properties = when_on_single_line:warning
+
+# IDE0026
+dotnet_diagnostic.ide0026.severity = suggestion
+csharp_style_expression_bodied_indexers = when_on_single_line:suggestion
+
+# IDE0027
+dotnet_diagnostic.ide0027.severity = suggestion
+csharp_style_expression_bodied_accessors = when_on_single_line:suggestion
+
+# IDE0028
+dotnet_diagnostic.ide0028.severity = suggestion
+dotnet_style_collection_initializer = true:suggestion
+
+# IDE0029 and IDE0030
+dotnet_diagnostic.ide0029.severity = suggestion
+dotnet_diagnostic.ide0030.severity = suggestion
+dotnet_style_coalesce_expression = true:suggestion
+
+# IDE0031
+dotnet_diagnostic.ide0031.severity = suggestion
+dotnet_style_null_propagation = true:suggestion
+
+# IDE0032
+dotnet_diagnostic.ide0032.severity = warning
+dotnet_style_prefer_auto_properties = true:warning
+
+# IDE0033
+dotnet_diagnostic.ide0033.severity = warning
+dotnet_style_explicit_tuple_names = true:warning
+
+# IDE0034
+dotnet_diagnostic.ide0034.severity = warning
+csharp_prefer_simple_default_expression = true:warning
+
+# IDE0035
+dotnet_diagnostic.ide0035.severity = warning
+
+# IDE0036
+dotnet_diagnostic.ide0036.severity = warning
+csharp_preferred_modifier_order = public, private, protected, internal, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, volatile, async
+
+# IDE0037
+dotnet_diagnostic.ide0037.severity = warning
+dotnet_style_prefer_inferred_tuple_names = true:warning
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
+
+# IDE0039
+dotnet_diagnostic.ide0039.severity = suggestion
+csharp_style_prefer_local_over_anonymous_function = true:suggestion
+
+# IDE0040
+dotnet_diagnostic.ide0040.severity = warning
+dotnet_style_require_accessibility_modifiers = always:warning
+
+# IDE0041
+dotnet_diagnostic.ide0041.severity = warning
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
+
+# IDE0042
+dotnet_diagnostic.ide0042.severity = suggestion
+csharp_style_deconstructed_variable_declaration = true:suggestion
+
+# IDE0044
+dotnet_diagnostic.ide0044.severity = warning
+dotnet_style_readonly_field = true:warning
+
+# IDE0045
+dotnet_diagnostic.ide0045.severity = suggestion
+dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
+
+# IDE0046
+dotnet_diagnostic.ide0046.severity = suggestion
+dotnet_style_prefer_conditional_expression_over_return = true:suggestion
+
+# IDE0047 and IDE0048
+dotnet_diagnostic.ide0047.severity = warning
+dotnet_diagnostic.ide0048.severity = warning
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary:warning
+
+# IDE0049
+dotnet_diagnostic.ide0049.severity = warning
+dotnet_style_predefined_type_for_locals_parameters_members = true:warning
+dotnet_style_predefined_type_for_member_access = true:warning
+
+# IDE0050-52
+dotnet_diagnostic.ide0050.severity = warning
+dotnet_diagnostic.ide0051.severity = warning
+dotnet_diagnostic.ide0052.severity = warning
+
+# IDE0053
+dotnet_diagnostic.ide0053.severity = suggestion
+csharp_style_expression_bodied_lambdas = true:suggestion
+
+# IDE0054 and IDE0074
+dotnet_diagnostic.ide0054.severity = suggestion
+dotnet_diagnostic.ide0074.severity = suggestion
+dotnet_style_prefer_compound_assignment = true:suggestion
+
+# IDE0055
+dotnet_sort_system_directives_first = false
+dotnet_separate_import_directive_groups = false
+dotnet_style_namespace_match_folder = true:warning
+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 = false
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = no_change
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents_when_block = false
+csharp_space_after_cast = false
+csharp_space_after_keywords_in_control_flow_statements = true
+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_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_after_comma = true
+csharp_space_before_comma = false
+csharp_space_after_dot = false
+csharp_space_before_dot = false
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_around_declaration_statements = false
+csharp_space_before_open_square_brackets = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_square_brackets = false
+csharp_preserve_single_line_statements = true
+csharp_preserve_single_line_blocks = true
+
+# IDE0056
+dotnet_diagnostic.ide0056.severity = warning
+csharp_style_prefer_index_operator = false:warning
+
+# IDE0057
+dotnet_diagnostic.ide0057.severity = warning
+csharp_style_prefer_range_operator = false:warning
+
+# IDE0058, IDE0059, IDE0060
+dotnet_diagnostic.ide0058.severity = none
+dotnet_diagnostic.ide0059.severity = none
+dotnet_diagnostic.ide0060.severity = none
+csharp_style_unused_value_expression_statement_preference = discard_variable:none
+csharp_style_unused_value_assignment_preference = discard_variable:none
+dotnet_code_quality_unused_parameters = all:none
+
+
+# IDE0061
+dotnet_diagnostic.ide0061.severity = suggestion
+csharp_style_expression_bodied_local_functions = false:suggestion
+
+# IDE0062
+dotnet_diagnostic.ide0062.severity = suggestion
+csharp_prefer_static_local_function = true:suggestion
+
+# IDE0063
+dotnet_diagnostic.ide0063.severity = warning
+csharp_prefer_simple_using_statement = true:warning
+
+# IDE0064
+dotnet_diagnostic.ide0064.severity = warning
+dotnet_diagnostic.ide0064.severity = none
+
+# IDE0065
+dotnet_diagnostic.ide0065.severity = warning
+csharp_using_directive_placement = outside_namespace:warning
+
+# IDE0066
+dotnet_diagnostic.ide0066.severity = warning
+csharp_style_prefer_switch_expression = true:warning
+
+# IDE0070
+dotnet_diagnostic.ide0070.severity = warning
+
+# IDE0071
+dotnet_diagnostic.ide0071.severity = none
+dotnet_style_prefer_simplified_interpolation = true:suggestion
+
+# IDE0072
+dotnet_diagnostic.ide0072.severity = warning
+
+# IDE0073
+file_header_template = unset
+
+# IDE0075
+dotnet_diagnostic.ide0075.severity = suggestion
+dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
+
+# IDE0078
+# dotnet_diagnostic.IDE0078.severity = warning
+# csharp_style_prefer_pattern_matching = true:suggestion
+csharp_style_prefer_pattern_matching = true:none
+
+# IDE0082
+dotnet_diagnostic.ide0082.severity = warning
+
+# IDE0083
+dotnet_diagnostic.ide0083.severity = warning
+csharp_style_prefer_not_pattern = true:warning
+
+# IDE0090
+dotnet_diagnostic.ide0090.severity = warning
+csharp_style_implicit_object_creation_when_type_is_apparent = false:warning
+
+# IDE0100
+dotnet_diagnostic.ide0100.severity = warning
+
+# IDE0110
+dotnet_diagnostic.ide0110.severity = warning
+
+# IDE0150
+dotnet_diagnostic.ide0150.severity = warning
+csharp_style_prefer_null_check_over_type_check = false:warning
+
+# IDE0160 and IDE0161
+dotnet_diagnostic.ide0161.severity = warning
+csharp_style_namespace_declarations = file_scoped:warning
+
+# IDE0170
+dotnet_diagnostic.ide0170.severity = none
+csharp_style_prefer_extended_property_pattern = true:none
+
+# IDE0180
+dotnet_diagnostic.ide0180.severity = suggestion
+csharp_style_prefer_tuple_swap = false:suggestion
+
+# IDE1005
+dotnet_diagnostic.ide1005.severity = suggestion
+csharp_style_conditional_delegate_call = true:suggestion
+
+dotnet_diagnostic.ca1000.severity = none
+dotnet_diagnostic.ca1001.severity = warning
+dotnet_diagnostic.ca1002.severity = warning
+dotnet_diagnostic.ca1003.severity = none
+dotnet_diagnostic.ca1005.severity = none
+dotnet_diagnostic.ca1008.severity = none
+dotnet_diagnostic.ca1010.severity = warning
+dotnet_diagnostic.ca1012.severity = warning
+dotnet_diagnostic.ca1014.severity = none
+dotnet_diagnostic.ca1016.severity = none
+dotnet_diagnostic.ca1017.severity = none
+dotnet_diagnostic.ca1018.severity = warning
+dotnet_diagnostic.ca1019.severity = warning
+dotnet_diagnostic.ca1021.severity = warning
+dotnet_diagnostic.ca1024.severity = suggestion
+dotnet_diagnostic.ca1027.severity = none
+dotnet_diagnostic.ca1028.severity = warning
+dotnet_diagnostic.ca1030.severity = none
+dotnet_diagnostic.ca1031.severity = none
+dotnet_diagnostic.ca1032.severity = none
+dotnet_diagnostic.ca1033.severity = none
+dotnet_diagnostic.ca1034.severity = none
+dotnet_diagnostic.ca1036.severity = silent
+dotnet_diagnostic.ca1040.severity = none
+dotnet_diagnostic.ca1041.severity = suggestion
+dotnet_diagnostic.ca1043.severity = none
+dotnet_diagnostic.ca1044.severity = warning
+dotnet_diagnostic.ca1045.severity = warning
+dotnet_diagnostic.ca1046.severity = suggestion
+dotnet_diagnostic.ca1047.severity = warning
+dotnet_diagnostic.ca1050.severity = warning
+dotnet_diagnostic.ca1051.severity = warning
+dotnet_diagnostic.ca1052.severity = none
+dotnet_diagnostic.ca1053.severity = none
+dotnet_diagnostic.ca1054.severity = suggestion
+dotnet_diagnostic.ca1055.severity = suggestion
+dotnet_diagnostic.ca1056.severity = suggestion
+dotnet_diagnostic.ca1058.severity = warning
+dotnet_diagnostic.ca1060.severity = none
+dotnet_diagnostic.ca1061.severity = warning
+dotnet_diagnostic.ca1062.severity = none
+dotnet_diagnostic.ca1063.severity = none
+dotnet_diagnostic.ca1064.severity = warning
+dotnet_diagnostic.ca1065.severity = warning
+dotnet_diagnostic.ca1067.severity = warning
+dotnet_diagnostic.ca1068.severity = suggestion
+dotnet_diagnostic.ca1069.severity = warning
+dotnet_diagnostic.ca1079.severity = warning
+dotnet_diagnostic.ca1200.severity = none
+dotnet_diagnostic.ca1303.severity = none
+dotnet_diagnostic.ca1304.severity = none
+dotnet_diagnostic.ca1305.severity = none
+dotnet_diagnostic.ca1307.severity = warning
+dotnet_diagnostic.ca1308.severity = suggestion
+dotnet_diagnostic.ca1309.severity = suggestion
+dotnet_diagnostic.ca1310.severity = suggestion
+dotnet_diagnostic.ca1401.severity = warning
+dotnet_diagnostic.ca1416.severity = warning
+dotnet_diagnostic.ca1417.severity = warning
+dotnet_diagnostic.ca1418.severity = warning
+dotnet_diagnostic.ca1419.severity = warning
+dotnet_diagnostic.ca1501.severity = warning
+dotnet_diagnostic.ca1502.severity = warning
+dotnet_diagnostic.ca1505.severity = warning
+dotnet_diagnostic.ca1506.severity = warning
+dotnet_diagnostic.ca1507.severity = suggestion
+dotnet_diagnostic.ca1508.severity = warning
+# dotnet_diagnostic.CA1509.severity = none
+dotnet_diagnostic.ca1700.severity = none
+dotnet_diagnostic.ca1707.severity = warning
+dotnet_diagnostic.ca1708.severity = none
+dotnet_diagnostic.ca1710.severity = none
+dotnet_diagnostic.ca1711.severity = none
+dotnet_diagnostic.ca1712.severity = none
+dotnet_diagnostic.ca1713.severity = none
+dotnet_diagnostic.ca1714.severity = suggestion
+dotnet_diagnostic.ca1715.severity = warning
+dotnet_diagnostic.ca1716.severity = warning
+dotnet_diagnostic.ca1717.severity = none
+dotnet_diagnostic.ca1720.severity = warning
+dotnet_diagnostic.ca1721.severity = warning
+dotnet_diagnostic.ca1724.severity = warning
+dotnet_diagnostic.ca1725.severity = warning
+dotnet_diagnostic.ca1727.severity = none
+dotnet_diagnostic.ca1801.severity = warning
+dotnet_diagnostic.ca1802.severity = warning
+dotnet_diagnostic.ca1805.severity = none
+dotnet_diagnostic.ca1806.severity = none
+dotnet_diagnostic.ca1810.severity = none
+dotnet_diagnostic.ca1812.severity = none
+# dotnet_diagnostic.CA1812.severity = warning
+dotnet_diagnostic.ca1813.severity = warning
+dotnet_diagnostic.ca1814.severity = warning
+dotnet_diagnostic.ca1815.severity = suggestion
+dotnet_diagnostic.ca1816.severity = none
+dotnet_diagnostic.ca1819.severity = none
+dotnet_diagnostic.ca1820.severity = warning
+dotnet_diagnostic.ca1821.severity = warning
+dotnet_diagnostic.ca1822.severity = none
+dotnet_diagnostic.ca1823.severity = warning
+dotnet_diagnostic.ca1824.severity = none
+dotnet_diagnostic.ca1825.severity = warning
+dotnet_diagnostic.ca1826.severity = none
+dotnet_diagnostic.ca1827.severity = warning
+dotnet_diagnostic.ca1828.severity = warning
+dotnet_diagnostic.ca1829.severity = warning
+dotnet_diagnostic.ca1830.severity = suggestion
+dotnet_diagnostic.ca1831.severity = suggestion
+dotnet_diagnostic.ca1832.severity = suggestion
+dotnet_diagnostic.ca1833.severity = suggestion
+dotnet_diagnostic.ca1834.severity = suggestion
+dotnet_diagnostic.ca1835.severity = suggestion
+dotnet_diagnostic.ca1836.severity = warning
+dotnet_diagnostic.ca1837.severity = warning
+dotnet_diagnostic.ca1838.severity = warning
+dotnet_diagnostic.ca1841.severity = none
+dotnet_diagnostic.ca1842.severity = none
+dotnet_diagnostic.ca1843.severity = none
+dotnet_diagnostic.ca1844.severity = warning
+dotnet_diagnostic.ca1845.severity = suggestion
+dotnet_diagnostic.ca1846.severity = suggestion
+dotnet_diagnostic.ca1847.severity = suggestion
+dotnet_diagnostic.ca1848.severity = none
+dotnet_diagnostic.ca1849.severity = suggestion
+dotnet_diagnostic.ca1850.severity = suggestion
+dotnet_diagnostic.ca1851.severity = warning
+dotnet_diagnostic.ca1854.severity = suggestion
+dotnet_diagnostic.ca2000.severity = suggestion
+# dotnet_diagnostic.CA2000.severity = warning
+dotnet_diagnostic.ca2002.severity = none
+dotnet_diagnostic.ca2008.severity = none
+dotnet_diagnostic.ca2009.severity = warning
+dotnet_diagnostic.ca2011.severity = warning
+dotnet_diagnostic.ca2012.severity = warning
+dotnet_diagnostic.ca2013.severity = warning
+dotnet_diagnostic.ca2014.severity = warning
+dotnet_diagnostic.ca2015.severity = warning
+dotnet_diagnostic.ca2016.severity = suggestion
+dotnet_diagnostic.ca2017.severity = warning
+dotnet_diagnostic.ca2018.severity = warning
+dotnet_diagnostic.ca2100.severity = warning
+dotnet_diagnostic.ca2101.severity = none
+dotnet_diagnostic.ca2201.severity = suggestion
+# dotnet_diagnostic.CA2201.severity = warning
+dotnet_diagnostic.ca2207.severity = warning
+dotnet_diagnostic.ca2208.severity = warning
+dotnet_diagnostic.ca2211.severity = suggestion
+dotnet_diagnostic.ca2213.severity = warning
+dotnet_diagnostic.ca2214.severity = suggestion
+dotnet_diagnostic.ca2215.severity = warning
+dotnet_diagnostic.ca2216.severity = none
+dotnet_diagnostic.ca2217.severity = none
+dotnet_diagnostic.ca2218.severity = warning
+dotnet_diagnostic.ca2219.severity = warning
+dotnet_diagnostic.ca2224.severity = warning
+dotnet_diagnostic.ca2225.severity = none
+dotnet_diagnostic.ca2226.severity = suggestion
+dotnet_diagnostic.ca2227.severity = warning
+dotnet_diagnostic.ca2229.severity = none
+dotnet_diagnostic.ca2231.severity = suggestion
+dotnet_diagnostic.ca2234.severity = silent
+dotnet_diagnostic.ca2235.severity = none
+dotnet_diagnostic.ca2237.severity = none
+dotnet_diagnostic.ca2241.severity = warning
+dotnet_diagnostic.ca2242.severity = warning
+dotnet_diagnostic.ca2243.severity = warning
+dotnet_diagnostic.ca2244.severity = warning
+dotnet_diagnostic.ca2245.severity = warning
+dotnet_diagnostic.ca2246.severity = warning
+dotnet_diagnostic.ca2247.severity = warning
+dotnet_diagnostic.ca2248.severity = warning
+dotnet_diagnostic.ca2249.severity = warning
+dotnet_diagnostic.ca2250.severity = warning
+dotnet_diagnostic.ca2251.severity = warning
+dotnet_diagnostic.ca2252.severity = none
+dotnet_diagnostic.ca2253.severity = warning
+dotnet_diagnostic.ca2254.severity = none
+dotnet_diagnostic.ca2255.severity = none
+dotnet_diagnostic.ca2256.severity = none
+dotnet_diagnostic.ca2257.severity = none
+dotnet_diagnostic.ca2258.severity = none
+
+# IDE1006
+dotnet_diagnostic.ide1006.severity = warning
+
+# camel_case_style - Define the camelCase style
+dotnet_naming_style.camel_case_style.capitalization = camel_case
+# pascal_case_style - Define the PascalCase style
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+# first_upper_style - The first character must start with an upper-case character
+dotnet_naming_style.first_upper_style.capitalization = first_word_upper
+# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I'
+dotnet_naming_style.prefix_interface_with_i_style.capitalization = pascal_case
+dotnet_naming_style.prefix_interface_with_i_style.required_prefix = I
+# prefix_type_parameters_with_t_style - Generic Type Parameters must be PascalCase and the first character must be a 'T'
+dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization = pascal_case
+dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T
+# disallowed_style - Anything that has this style applied is marked as disallowed
+dotnet_naming_style.disallowed_style.capitalization = pascal_case
+dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____
+dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____
+dotnet_naming_style.internal_error_style.capitalization = pascal_case
+dotnet_naming_style.internal_error_style.required_prefix = ____INTERNAL_ERROR____
+dotnet_naming_style.internal_error_style.required_suffix = ____INTERNAL_ERROR____
+
+dotnet_naming_symbols.public_protected_constant_fields_group.applicable_accessibilities = public, protected, protected_internal
+dotnet_naming_symbols.public_protected_constant_fields_group.required_modifiers = const
+dotnet_naming_symbols.public_protected_constant_fields_group.applicable_kinds = field
+dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.symbols = public_protected_constant_fields_group
+dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.style = pascal_case_style
+dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.severity = warning
+
+dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_accessibilities = public, protected, protected_internal
+dotnet_naming_symbols.public_protected_static_readonly_fields_group.required_modifiers = static, readonly
+dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_kinds = field
+dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.symbols = public_protected_static_readonly_fields_group
+dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style
+dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.severity = warning
+
+dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibilities = public, protected, protected_internal
+dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = field
+dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols = other_public_protected_fields_group
+dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style
+dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error
+
+# Other
+
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+
+
+# Not verified
+
+csharp_style_prefer_method_group_conversion = true:silent
+csharp_style_prefer_top_level_statements = true:silent
+csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
+csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
+csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
+dotnet_style_allow_multiple_blank_lines_experimental = true:silent
+dotnet_style_allow_statement_immediately_after_block_experimental = true:silent
+# IDE0230
+csharp_style_prefer_utf8_string_literals = true:suggestion
+
+# ReSharper
+resharper_csharp_empty_block_style = together_same_line
+
+csharp_wrap_arguments_style = chop_if_long
+csharp_wrap_chained_method_calls = chop_if_long
+
+# ReSharper properties
+resharper_csharp_wrap_after_declaration_lpar = true
+resharper_csharp_wrap_parameters_style = chop_if_long
\ No newline at end of file
diff --git a/Directory.Packages.props b/Directory.Packages.props
index a9605f2..cb85987 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -4,15 +4,22 @@
false
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/src/Application/DoctorsHelp.Application/DoctorsHelp.Application.csproj b/src/Application/DoctorsHelp.Application/DoctorsHelp.Application.csproj
index af83562..92540d4 100644
--- a/src/Application/DoctorsHelp.Application/DoctorsHelp.Application.csproj
+++ b/src/Application/DoctorsHelp.Application/DoctorsHelp.Application.csproj
@@ -7,6 +7,9 @@
+
+
+
\ No newline at end of file
diff --git a/src/Application/DoctorsHelp.Application/Extensions/ServiceCollectionExtensions.cs b/src/Application/DoctorsHelp.Application/Extensions/ServiceCollectionExtensions.cs
index f0449dc..e7883b2 100644
--- a/src/Application/DoctorsHelp.Application/Extensions/ServiceCollectionExtensions.cs
+++ b/src/Application/DoctorsHelp.Application/Extensions/ServiceCollectionExtensions.cs
@@ -1,3 +1,5 @@
+using DoctorsHelp.Application.Contracts;
+using DoctorsHelp.Application.Models;
using Microsoft.Extensions.DependencyInjection;
namespace DoctorsHelp.Application.Extensions;
@@ -6,7 +8,6 @@ public static class ServiceCollectionExtensions
{
public static IServiceCollection AddApplication(this IServiceCollection collection)
{
- // TODO: add services
return collection;
}
}
\ No newline at end of file
diff --git a/src/DoctorsHelp/DoctorsHelp.csproj b/src/DoctorsHelp/DoctorsHelp.csproj
index f201af4..8dfbbaa 100644
--- a/src/DoctorsHelp/DoctorsHelp.csproj
+++ b/src/DoctorsHelp/DoctorsHelp.csproj
@@ -1,16 +1,27 @@
-
-
+
+
-
+
+
+
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+
diff --git a/src/DoctorsHelp/Program.cs b/src/DoctorsHelp/Program.cs
index 7fe3860..c463102 100644
--- a/src/DoctorsHelp/Program.cs
+++ b/src/DoctorsHelp/Program.cs
@@ -3,6 +3,9 @@
using DoctorsHelp.Application.Extensions;
using DoctorsHelp.Infrastructure.Persistence.Extensions;
using DoctorsHelp.Presentation.Http.Extensions;
+using DotNet.Testcontainers.Builders;
+using DotNet.Testcontainers.Configurations;
+using DotNet.Testcontainers.Containers;
using Itmo.Dev.Platform.Common.Extensions;
using Itmo.Dev.Platform.Logging.Extensions;
using Microsoft.Extensions.Options;
@@ -10,13 +13,29 @@
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
+var postgresContainer = new TestcontainersBuilder()
+ .WithDatabase(new PostgreSqlTestcontainerConfiguration
+ {
+ Database = "postgres",
+ Username = "postgres",
+ Password = "postgres",
+ })
+ .Build();
+
+await postgresContainer.StartAsync();
+
+// builder.Configuration["Infrastructure:Persistence:Postgres:Host"] = postgresContainer.Hostname;
+// builder.Configuration["Infrastructure:Persistence:Postgres:Port"] = postgresContainer.Port.ToString();
+// builder.Configuration["Infrastructure:Persistence:Postgres:Username"] = postgresContainer.Username;
+// builder.Configuration["Infrastructure:Persistence:Postgres:Password"] = postgresContainer.Password;
+// builder.Configuration["Infrastructure:Persistence:Postgres:Database"] = postgresContainer.Database;
builder.Configuration.AddUserSecrets();
builder.Services.AddOptions();
builder.Services.AddSingleton(sp => sp.GetRequiredService>().Value);
builder.Services.AddApplication();
-builder.Services.AddInfrastructurePersistence();
+builder.Services.AddInfrastructurePersistence(builder.Configuration);
builder.Services
.AddControllers()
.AddNewtonsoftJson()
diff --git a/src/DoctorsHelp/appsettings.Local.json b/src/DoctorsHelp/appsettings.Local.json
index a26180e..35a3216 100644
--- a/src/DoctorsHelp/appsettings.Local.json
+++ b/src/DoctorsHelp/appsettings.Local.json
@@ -8,7 +8,8 @@
"Username": "postgres",
"Password": "postgres",
"SslMode": "Prefer",
- "Pooling": true
+ "Pooling": true,
+ "ConnectionString": "Host=localhost;Port=6432;Database=postgres;Username=postgres;Password=postgres;SslMode=Prefer;Pooling=true"
}
}
},
diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Contexts/ApplicationDbContext.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Contexts/ApplicationDbContext.cs
new file mode 100644
index 0000000..a78e81e
--- /dev/null
+++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Contexts/ApplicationDbContext.cs
@@ -0,0 +1,19 @@
+using DoctorsHelp.Application.Models;
+using Microsoft.EntityFrameworkCore;
+
+namespace DoctorsHelp.Infrastructure.Persistence.Contexts;
+
+public class ApplicationDbContext : DbContext
+{
+ public ApplicationDbContext() { }
+
+ public ApplicationDbContext(DbContextOptions options) : base(options) { }
+
+ required public DbSet Students { get; set; }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ modelBuilder.ApplyConfigurationsFromAssembly(typeof(ApplicationDbContext).Assembly);
+ base.OnModelCreating(modelBuilder);
+ }
+}
\ No newline at end of file
diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/DoctorsHelp.Infrastructure.Persistence.csproj b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/DoctorsHelp.Infrastructure.Persistence.csproj
index 2aec2b3..8f50280 100644
--- a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/DoctorsHelp.Infrastructure.Persistence.csproj
+++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/DoctorsHelp.Infrastructure.Persistence.csproj
@@ -2,6 +2,10 @@
+
+
+
+
diff --git a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Extensions/ServiceCollectionExtensions.cs b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Extensions/ServiceCollectionExtensions.cs
index dbad899..6f86984 100644
--- a/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Extensions/ServiceCollectionExtensions.cs
+++ b/src/Infrastructure/DoctorsHelp.Infrastructure.Persistence/Extensions/ServiceCollectionExtensions.cs
@@ -1,15 +1,18 @@
using DoctorsHelp.Application.Abstractions.Persistence;
+using DoctorsHelp.Infrastructure.Persistence.Contexts;
using DoctorsHelp.Infrastructure.Persistence.Migrations;
using DoctorsHelp.Infrastructure.Persistence.Plugins;
using Itmo.Dev.Platform.Postgres.Extensions;
using Itmo.Dev.Platform.Postgres.Plugins;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace DoctorsHelp.Infrastructure.Persistence.Extensions;
public static class ServiceCollectionExtensions
{
- public static IServiceCollection AddInfrastructurePersistence(this IServiceCollection collection)
+ public static IServiceCollection AddInfrastructurePersistence(this IServiceCollection collection, IConfiguration configuration)
{
collection.AddPlatformPostgres(builder => builder.BindConfiguration("Infrastructure:Persistence:Postgres"));
collection.AddSingleton();
@@ -17,7 +20,8 @@ public static IServiceCollection AddInfrastructurePersistence(this IServiceColle
collection.AddPlatformMigrations(typeof(IAssemblyMarker).Assembly);
collection.AddHostedService();
- // TODO: add repositories
+ collection.AddDbContext(options =>
+ options.UseNpgsql(configuration.GetSection("Infrastructure:Persistence:Postgres:ConnectionString").Value));
collection.AddScoped();
return collection;