diff --git a/.editorconfig b/.editorconfig
index b77a3d33..b388e303 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,208 +1,49 @@
-# See https://github.com/RehanSaeed/EditorConfig/releases for release notes.
-# See https://github.com/RehanSaeed/EditorConfig for updates to this file.
-# See http://EditorConfig.org for more information about .editorconfig files.
+# https://editorconfig.org
+# https://www.jetbrains.com/help/resharper/Using_EditorConfig.html
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-files
+# When opening a file, EditorConfig plugins look for a file named .editorconfig in the directory of the opened file and in every parent directory. A search for .editorconfig files will stop if the root filepath is reached or an EditorConfig file with `root=true` is found.
-##########################################
-# Common Settings
-##########################################
+# Remove the line below if you want to inherit .editorconfig settings from higher directories
+
+##################################################################################
+## https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/
+## https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/
+## Microsoft Rules
+##
-# This file is the top-most EditorConfig file
root = true
+# EditorConfig is awesome: http://EditorConfig.org
+
+# top-most EditorConfig file
-# All Files
+# Global settings
[*]
charset = utf-8
-indent_style = space
+end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
-##########################################
-# File Extension Settings
-##########################################
-
-# Visual Studio Solution Files
-[*.sln]
-indent_style = tab
-
-# Visual Studio XML Project Files
-[*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}]
-indent_size = 2
-
-# XML Configuration Files
-[*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}]
-indent_size = 2
-
-# JSON Files
-[*.{json,json5,webmanifest}]
-indent_size = 2
-
-# YAML Files
-[*.{yml,yaml}]
+# Xml project files
+[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
+indent_style = space
indent_size = 2
-# Markdown Files
-[*.{md,mdx}]
-trim_trailing_whitespace = false
-
-# Web Files
-[*.{htm,html,js,jsm,ts,tsx,cjs,cts,ctsx,mjs,mts,mtsx,css,sass,scss,less,pcss,svg,vue}]
+# Xml config files
+[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
+indent_style = space
indent_size = 2
-# Batch Files
-[*.{cmd,bat}]
-end_of_line = crlf
+[*.{md,json}]
+indent_style = space
+indent_size = 4
-# Bash Files
-[*.sh]
-end_of_line = lf
+[*.cs]
+indent_style = space
+indent_size = 4
+max_line_length = 100
-# Makefiles
-[Makefile]
-indent_style = tab
-
-##########################################
-# Default .NET Code Style Severities
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/configuration-options#scope
-##########################################
-
-[*.{cs,csx,cake,vb,vbx}]
-# Default Severity for all .NET Code Style rules below
-dotnet_analyzer_diagnostic.severity = warning
-
-##########################################
-# Language Rules
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules
-##########################################
-
-# .NET Style Rules
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#net-style-rules
-[*.{cs,csx,cake,vb,vbx}]
-# "this." and "Me." qualifiers
-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 instead of framework type names for type references
-dotnet_style_predefined_type_for_locals_parameters_members = true:warning
-dotnet_style_predefined_type_for_member_access = true:warning
-# Modifier preferences
-dotnet_style_require_accessibility_modifiers = always:warning
-csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning
-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:warning
-dotnet_style_readonly_field = true:warning
-# Parentheses preferences
-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
-# Expression-level preferences
-dotnet_style_object_initializer = true:warning
-dotnet_style_collection_initializer = true:warning
-dotnet_style_explicit_tuple_names = true:warning
-dotnet_style_prefer_inferred_tuple_names = true:warning
-dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
-dotnet_style_prefer_auto_properties = true:warning
-dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion
-dotnet_diagnostic.IDE0045.severity = suggestion
-dotnet_style_prefer_conditional_expression_over_return = false:suggestion
-dotnet_diagnostic.IDE0046.severity = suggestion
-dotnet_style_prefer_compound_assignment = true:warning
-dotnet_style_prefer_simplified_interpolation = true:warning
-dotnet_style_prefer_simplified_boolean_expressions = true:warning
-# Null-checking preferences
-dotnet_style_coalesce_expression = true:warning
-dotnet_style_null_propagation = true:warning
-dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
-# File header preferences
-# file_header_template = \n© PROJECT-AUTHOR\n
-# If you use StyleCop, you'll need to disable SA1636: File header copyright text should match.
-# dotnet_diagnostic.SA1636.severity = none
-# Undocumented
-dotnet_style_operator_placement_when_wrapping = end_of_line:warning
-csharp_style_prefer_null_check_over_type_check = true:warning
-
-# C# Style Rules
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#c-style-rules
-[*.{cs,csx,cake}]
-# 'var' preferences
-csharp_style_var_for_built_in_types = true:warning
-csharp_style_var_when_type_is_apparent = true:warning
-csharp_style_var_elsewhere = true:warning
-# Expression-bodied members
-csharp_style_expression_bodied_methods = false:warning
-csharp_style_expression_bodied_constructors = false:warning
-csharp_style_expression_bodied_operators = false:silent
-csharp_style_expression_bodied_properties = false:silent
-csharp_style_expression_bodied_indexers = false:silent
-csharp_style_expression_bodied_accessors = false:silent
-csharp_style_expression_bodied_lambdas = false:silent
-csharp_style_expression_bodied_local_functions = false:silent
-# Pattern matching preferences
-csharp_style_pattern_matching_over_is_with_cast_check = true:warning
-csharp_style_pattern_matching_over_as_with_null_check = true:warning
-csharp_style_prefer_switch_expression = true:warning
-csharp_style_prefer_pattern_matching = true:warning
-csharp_style_prefer_not_pattern = true:warning
-# Expression-level preferences
-csharp_style_inlined_variable_declaration = true:warning
-csharp_prefer_simple_default_expression = true:warning
-csharp_style_pattern_local_over_anonymous_function = true:warning
-csharp_style_deconstructed_variable_declaration = true:warning
-csharp_style_prefer_index_operator = true:warning
-csharp_style_prefer_range_operator = true:warning
-csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
-# "Null" checking preferences
-csharp_style_throw_expression = true:warning
-csharp_style_conditional_delegate_call = true:warning
-# Code block preferences
-csharp_prefer_braces = true:warning
-csharp_prefer_simple_using_statement = true:suggestion
-dotnet_diagnostic.IDE0063.severity = suggestion
-# 'using' directive preferences
-csharp_using_directive_placement = inside_namespace:warning
-# Modifier preferences
-csharp_prefer_static_local_function = true:warning
-
-##########################################
-# Unnecessary Code Rules
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/unnecessary-code-rules
-##########################################
-
-# .NET Unnecessary code rules
-[*.{cs,csx,cake,vb,vbx}]
-dotnet_code_quality_unused_parameters = all:warning
-dotnet_remove_unnecessary_suppression_exclusions = none:warning
-
-# C# Unnecessary code rules
-[*.{cs,csx,cake}]
-csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
-dotnet_diagnostic.IDE0058.severity = suggestion
-csharp_style_unused_value_assignment_preference = discard_variable:suggestion
-dotnet_diagnostic.IDE0059.severity = suggestion
-
-##########################################
-# Formatting Rules
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules
-##########################################
-
-# .NET formatting rules
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#net-formatting-rules
-[*.{cs,csx,cake,vb,vbx}]
-# Organize using directives
-dotnet_sort_system_directives_first = true
-dotnet_separate_import_directive_groups = false
-# Dotnet namespace options
-dotnet_style_namespace_match_folder = false
-dotnet_diagnostic.IDE0130.severity = none
-
-[*.{cs,vb}]
-dotnet_diagnostic.CA1305.severity = none
-
-# C# formatting rules
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#c-formatting-rules
-[*.{cs,csx,cake}]
-# Newline options
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#new-line-options
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/csharp-formatting-options
+# New line preferences
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
@@ -210,215 +51,685 @@ 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 options
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#indentation-options
-csharp_indent_case_contents = true
-csharp_indent_switch_labels = true
-csharp_indent_labels = no_change
+
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/csharp-formatting-options#indentation-options
+# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
-csharp_indent_case_contents_when_block = false
-# Spacing options
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#spacing-options
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = one_less_than_current
+
+# avoid this. unless absolutely necessary
+dotnet_style_qualification_for_field = false:suggestion
+dotnet_style_qualification_for_property = false:suggestion
+dotnet_style_qualification_for_method = false:suggestion
+dotnet_style_qualification_for_event = false:suggestion
+
+# only use var when it's obvious what the variable type is
+# csharp_style_var_for_built_in_types = false:none
+# csharp_style_var_when_type_is_apparent = false:none
+# csharp_style_var_elsewhere = false:suggestion
+
+# use language keywords instead of BCL types
+dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
+dotnet_style_predefined_type_for_member_access = true:suggestion
+
+# name all constant fields using PascalCase
+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.required_modifiers = const
+
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+
+dotnet_naming_symbols.static_fields.applicable_kinds = field
+dotnet_naming_symbols.static_fields.required_modifiers = static
+
+dotnet_naming_style.static_prefix_style.required_prefix = s_
+dotnet_naming_style.static_prefix_style.capitalization = camel_case
+
+# internal and private fields should be _camelCase
+dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
+dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
+dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
+
+dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
+dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
+
+dotnet_naming_style.camel_case_underscore_style.required_prefix = _
+dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
+
+# Code style defaults
+dotnet_sort_system_directives_first = true
+csharp_preserve_single_line_blocks = true
+csharp_preserve_single_line_statements = false
+
+# Expression-level preferences
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+
+# Expression-bodied members
+csharp_style_expression_bodied_methods = false:none
+csharp_style_expression_bodied_constructors = false:none
+csharp_style_expression_bodied_operators = false:none
+csharp_style_expression_bodied_properties = true:none
+csharp_style_expression_bodied_indexers = true:none
+csharp_style_expression_bodied_accessors = true:none
+
+# Pattern matching
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+
+# Null checking preferences
+csharp_style_throw_expression = true:suggestion
+csharp_style_conditional_delegate_call = true:suggestion
+
+# Space preferences
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_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
-csharp_space_before_semicolon_in_for_statement = false
-csharp_space_around_declaration_statements = false
+csharp_space_around_binary_operators = before_and_after
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_before_comma = false
+csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
+csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_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_declaration_parameter_list_parentheses = false
+csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
-# Wrap options
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#wrap-options
-csharp_preserve_single_line_statements = false
-csharp_preserve_single_line_blocks = true
-# Namespace options
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#namespace-options
-csharp_style_namespace_declarations = file_scoped:warning
-##########################################
-# .NET Naming Rules
-# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/naming-rules
-##########################################
-[*.{cs,csx,cake,vb,vbx}]
+##################################################################################
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/
+##################################################################################
+## Roslyn Code quality rules
+
+dotnet_diagnostic.CA1030.severity = none
+dotnet_diagnostic.CA1034.severity = none
+dotnet_diagnostic.CA1062.severity = suggestion
+dotnet_code_quality.CA1062.exclude_extension_method_this_parameter = true
+dotnet_code_quality.exclude_extension_method_this_parameter = true
+dotnet_code_quality.null_check_validation_methods = ThrowIfArgumentIsNull
+# CA1031: Do not catch general exception types
+dotnet_diagnostic.CA1031.severity = none
+# CA1303: Do not pass literals as localized parameters
+dotnet_diagnostic.CA1303.severity = none
+# CA1304: Specify CultureInfo
+dotnet_diagnostic.CA1304.severity = error
+# CA1307: Specify StringComparison for clarity
+dotnet_diagnostic.CA1307.severity = error
+# CA1308: Normalize strings to uppercase
+dotnet_diagnostic.CA1308.severity = error
+# CA1309: Use ordinal StringComparison
+dotnet_diagnostic.CA1309.severity = error
+# CA1724: Type names should not match namespaces
+dotnet_diagnostic.CA1724.severity = none
+# CA1819: Properties should not return arrays
+dotnet_diagnostic.CA1819.severity = none
+# CA1851: Possible multiple enumerations of IEnumerable collection. Related to GH-issue #2000
+dotnet_diagnostic.CA1851.severity = suggestion
+# CA1859: Use concrete types when possible for improved performance
+dotnet_diagnostic.CA1859.severity = suggestion
+# CA1860: Avoid using 'Enumerable.Any()' extension method
+dotnet_diagnostic.CA1860.severity = warning
+# CA1861: Avoid constant arrays as arguments
+dotnet_diagnostic.CA1861.severity = none
+# CA2007: Do not directly await a Task
+dotnet_diagnostic.CA2007.severity = none
+# CA2225: Operator overloads have named alternates
+dotnet_diagnostic.CA2225.severity = none
+# CA3075: Insecure DTD Processing
+dotnet_diagnostic.CA3075.severity = none
+# CA5369: Use XmlReader for Deserialize
+dotnet_diagnostic.CA5369.severity = none
+# CA1305: Specify IFormatProvider
+dotnet_diagnostic.CA1305.severity = None
+# CA1063: Implement IDisposable correctly
+dotnet_diagnostic.CA1063.severity = None
+# CA2201: Do not raise reserved exception types
+dotnet_diagnostic.ca2201.severity = Suggestion
+# CA1848: Use the LoggerMessage delegates
+dotnet_diagnostic.ca1848.severity = Suggestion
+# CA1810: Initialize reference type static fields inline
+dotnet_diagnostic.ca1810.severity = Suggestion
+# CA1725: Parameter names should match base declaration
+dotnet_diagnostic.ca1725.severity = Suggestion
+# https://csharpier.com/docs/IntegratingWithLinters#code-analysis-rules
+
+##################################################################################
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/
+##################################################################################
+## Roslyn Code-style rules
+
+dotnet_diagnostic.IDE0048.severity = Suggestion
+dotnet_diagnostic.IDE0028.severity = Suggestion
+dotnet_diagnostic.IDE0029.severity = Suggestion
+dotnet_diagnostic.IDE0030.severity = Suggestion
+dotnet_diagnostic.IDE0004.severity = error
+
+# IDE0005: Remove unnecessary usings/imports
+dotnet_diagnostic.IDE0005.severity = warning
+
+# IDE0051: Remove unused private members (no reads or writes)
+dotnet_diagnostic.IDE0051.severity = Suggestion
+
+# IDE0052: Remove unread private members (writes but no reads)
+dotnet_diagnostic.IDE0052.severity = error
+
+# IDE0055: Fix formatting
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/csharp-formatting-options
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/dotnet-formatting-options
+# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0055
+dotnet_diagnostic.IDE0055.severity = suggestion
+
+# CS1574: XML comment on 'construct' has syntactically incorrect cref attribute 'name'
+dotnet_diagnostic.CS1574.severity = error
+
+##################################################################################
+# https://jetbrains.com.xy2401.com/help/resharper/EditorConfig_Index.html
+# https://jetbrains.com.xy2401.com/help/resharper/Reference__Code_Inspections_CSHARP.html
+## Resharper
+
+# ReSharper properties
+resharper_align_linq_query = true
+resharper_align_multiline_array_and_object_initializer = true
+resharper_align_multiline_binary_patterns = true
+resharper_align_multiline_expression = true
+resharper_align_multiline_extends_list = true
+resharper_align_multiline_parameter = true
+resharper_align_multiline_property_pattern = true
+resharper_align_multiline_switch_expression = true
+resharper_align_multiple_declaration = true
+resharper_align_multline_type_parameter_constrains = true
+resharper_align_multline_type_parameter_list = true
+resharper_align_tuple_components = true
+resharper_braces_for_for = required_for_multiline
+resharper_braces_for_foreach = required_for_multiline
+resharper_braces_for_ifelse = required_for_multiline
+resharper_csharp_alignment_tab_fill_style = optimal_fill
+resharper_csharp_indent_type_constraints = false
+resharper_csharp_int_align_fix_in_adjacent = false
+resharper_csharp_outdent_commas = true
+resharper_csharp_stick_comment = false
+resharper_csharp_wrap_after_declaration_lpar = true
+resharper_csharp_wrap_after_invocation_lpar = true
+resharper_csharp_wrap_arguments_style = chop_if_long
+resharper_csharp_wrap_before_declaration_rpar = true
+resharper_csharp_wrap_before_first_type_parameter_constraint = true
+resharper_csharp_wrap_before_ternary_opsigns = false
+resharper_csharp_wrap_extends_list_style = chop_if_long
+resharper_csharp_wrap_multiple_declaration_style = wrap_if_long
+resharper_csharp_wrap_multiple_type_parameter_constraints_style = chop_always
+resharper_csharp_wrap_parameters_style = chop_if_long
+resharper_enforce_line_ending_style = true
+resharper_indent_anonymous_method_block = true
+resharper_indent_braces_inside_statement_conditions = false
+resharper_indent_nested_fixed_stmt = true
+resharper_indent_nested_foreach_stmt = true
+resharper_indent_nested_for_stmt = true
+resharper_indent_nested_lock_stmt = true
+resharper_indent_nested_usings_stmt = true
+resharper_indent_nested_while_stmt = true
+resharper_keep_existing_declaration_block_arrangement = true
+resharper_keep_existing_declaration_parens_arrangement = false
+resharper_keep_existing_embedded_arrangement = false
+resharper_keep_existing_embedded_block_arrangement = true
+resharper_keep_existing_enum_arrangement = true
+resharper_keep_existing_invocation_parens_arrangement = false
+resharper_keep_existing_property_patterns_arrangement = false
+resharper_keep_existing_switch_expression_arrangement = false
+resharper_max_array_initializer_elements_on_line = 700
+resharper_max_formal_parameters_on_line = 500
+resharper_max_invocation_arguments_on_line = 700
+resharper_new_line_before_while = true
+resharper_place_attribute_on_same_line = false
+resharper_place_linq_into_on_new_line = false
+resharper_place_simple_case_statement_on_same_line = if_owner_is_single_line
+resharper_place_simple_property_pattern_on_single_line = false
+resharper_show_autodetect_configure_formatting_tip = false
+resharper_space_within_single_line_array_initializer_braces = false
+resharper_trailing_comma_in_multiline_lists = true
+resharper_trailing_comma_in_singleline_lists = true
+resharper_use_heuristics_for_body_style = false
+resharper_use_indent_from_vs = false
+resharper_use_roslyn_logic_for_evident_types = true
+resharper_wrap_array_initializer_style = chop_always
+resharper_wrap_chained_binary_expressions = chop_if_long
+resharper_wrap_chained_binary_patterns = chop_if_long
+resharper_wrap_chained_method_calls = chop_if_long
+resharper_wrap_for_stmt_header_style = wrap_if_long
+resharper_wrap_switch_expression = chop_if_long
+resharper_wrap_verbatim_interpolated_strings = chop_if_long
+
+# ReSharper inspection severities
+resharper_arrange_accessor_owner_body_highlighting = none
+resharper_arrange_redundant_parentheses_highlighting = hint
+resharper_arrange_type_member_modifiers_highlighting = hint
+resharper_arrange_type_modifiers_highlighting = hint
+resharper_check_namespace_highlighting = none
+resharper_enforce_if_statement_braces_highlighting = hint
+resharper_inconsistent_naming_highlighting = suggestion
+resharper_static_member_in_generic_type_highlighting = none
+resharper_suggest_var_or_type_built_in_types_highlighting = hint
+resharper_suggest_var_or_type_elsewhere_highlighting = hint
+resharper_suggest_var_or_type_simple_types_highlighting = hint
+resharper_web_config_module_not_resolved_highlighting = warning
+resharper_web_config_type_not_resolved_highlighting = warning
+resharper_web_config_wrong_module_highlighting = warning
+
+# https://www.jetbrains.com/help/rider/ClassNeverInstantiated.Global.html
+resharper_class_never_instantiated_global_highlighting = none
+
+
+# Convert lambda expression to method group
+resharper_convert_closure_to_method_group_highlighting = none
+
+# Start each element in a object or collection initializer on a new line
+resharper_wrap_object_and_collection_initializer_style = chop_always
+
+# Force an empty line
+resharper_blank_lines_after_multiline_statements = 1
+
+# Don't remove existing line breaks
+resharper_keep_existing_initializer_arrangement = true
+resharper_keep_existing_arrangement = true
+
+# We care about that extra else after an else-if
+resharper_redundant_if_else_block_highlighting = none
+
+# Don't remove explicit default cases in switch statements
+resharper_redundant_empty_switch_section_highlighting = none
+
+resharper_align_multiline_binary_expressions_chain = false
+
+# Only use new() when the type is obvious
+resharper_object_creation_when_type_not_evident = explicitly_typed
+resharper_object_creation_when_type_evident = target_typed
+
+# Indent 4 spaces per necessary indention
+resharper_continuous_indent_multiplier = 1
+
+# Avoid breaking a generic definition
+resharper_wrap_before_extends_colon = true
+
+resharper_blank_lines_before_multiline_statements = 1
+
+resharper_parentheses_non_obvious_operations = arithmetic, multiplicative, equality, relational, additive
+resharper_parentheses_redundancy_style = remove_if_not_clarifies_precedence
+
+##################################################################################
+## https://github.com/bkoelman/CSharpGuidelinesAnalyzer
+## CSharpGuidelines
+##################################################################################
+
+dotnet_diagnostic.AV1561.max_parameter_count = 5
+# AV1008: Class should be non-static or its name should be suffixed with Extensions
+dotnet_diagnostic.AV1008.severity = none
+# AV1010: Type hides inherited member
+dotnet_diagnostic.AV1010.severity = none
+# AV1115: Member or local function contains the word 'and', which suggests doing multiple things
+dotnet_diagnostic.AV1115.severity = suggestion
+# AV1130: Return type in signature for Type should be a collection interface instead of a concrete type
+dotnet_diagnostic.AV1130.severity = none
+# AV1135: null is returned from method which has return type of string, collection or task
+dotnet_diagnostic.AV1135.severity = none # re-enable if we can distinguish between string, collection and task
+# AV1210: Catch a specific exception instead of Exception, SystemException or ApplicationException
+dotnet_diagnostic.AV1210.severity = none
+# AV1250: Evaluate LINQ query before returning it
+dotnet_diagnostic.AV1250.severity = suggestion
+# AV1500: Method 'CallerIdentifier.DetermineCallerIdentity()' contains 10 statements, which exceeds the maximum of 7 statements
+dotnet_diagnostic.AV1500.severity = none
+# AV1532: Loop statement contains nested loop
+dotnet_diagnostic.AV1532.severity = suggestion
+# AV1535: Missing block in case or default clause of switch statement
+dotnet_diagnostic.AV1535.severity = none # re-enable if we can adjust the formatting to not indent the scope braces
+# AV1537: If-else-if construct should end with an unconditional else clause
+dotnet_diagnostic.AV1537.severity = suggestion
+# AV1551: Method overload with the most parameters should be virtual
+dotnet_diagnostic.AV1551.severity = none
+# AV1555: Avoid using non-(nullable-)boolean named arguments
+dotnet_diagnostic.AV1555.severity = suggestion
+# AV1561: Method contains 5 parameters, which exceeds the maximum of 3 parameters
+dotnet_diagnostic.AV1561.severity = suggestion
+# AV1564: Parameter in public or internal member is of type bool or bool?
+dotnet_diagnostic.AV1564.severity = suggestion
+# AV1554: Do not use optional parameters in interface methods or their concrete implementations
+dotnet_diagnostic.AV1554.severity = none
+# AV1580: Argument for parameter calls nested method
+dotnet_diagnostic.AV1580.severity = none
+# AV1706: Parameter 'p' should have a more descriptive name
+dotnet_diagnostic.AV1706.severity = warning
+# AV1708: Type name contains term that should be avoided
+dotnet_diagnostic.AV1708.severity = suggestion
+# AV1710: Field contains the name of its containing type
+dotnet_diagnostic.AV1710.severity = none
+# AV2202: Replace call to Nullable.HasValue with null check
+dotnet_diagnostic.AV2202.severity = none
+# AV2305: Missing XML comment for internally visible type or member
+dotnet_diagnostic.AV2305.severity = none
+# AV2407: Region should be removed
+dotnet_diagnostic.AV2407.severity = none
+
+##################################################################################
+## https://github.com/DotNetAnalyzers/StyleCopAnalyzers/tree/master/documentation
+## https://documentation.help/StyleCop/StyleCop.html
+## StyleCop.Analyzers
+##################################################################################
-##########################################
-# Styles
-##########################################
+# Using directive should appear within a namespace declaration
+dotnet_diagnostic.sa1200.severity = None
-# 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____
-# internal_error_style - This style should never occur... if it does, it indicates a bug in file or in the parser using the file
-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____
-
-##########################################
-# .NET Design Guideline Field Naming Rules
-# Naming rules for fields follow the .NET Framework design guidelines
-# https://docs.microsoft.com/dotnet/standard/design-guidelines/index
-##########################################
-
-# All public/protected/protected_internal constant fields must be PascalCase
-# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
-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
-
-# All public/protected/protected_internal static readonly fields must be PascalCase
-# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
-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
-
-# No other public/protected/protected_internal fields are allowed
-# https://docs.microsoft.com/dotnet/standard/design-guidelines/field
-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 = none
-
-##########################################
-# StyleCop Field Naming Rules
-# Naming rules for fields follow the StyleCop analyzers
-# This does not override any rules using disallowed_style above
-# https://github.com/DotNetAnalyzers/StyleCopAnalyzers
-##########################################
-
-# All constant fields must be PascalCase
-# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md
-dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
-dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const
-dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field
-dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group
-dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = pascal_case_style
-dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity = warning
-
-# All static readonly fields must be PascalCase
-# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md
-dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private
-dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly
-dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field
-dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group
-dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style
-dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity = warning
-
-# No non-private instance fields are allowed
-# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md
-dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected
-dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field
-dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group
-dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style
-dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.severity = error
-
-# Private fields must be camelCase
-# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1306.md
-dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.symbols = stylecop_private_fields_group
-dotnet_naming_rule.private_members_with_underscore.symbols = private_fields
-dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore
-dotnet_naming_rule.private_members_with_underscore.severity = warning
-dotnet_naming_symbols.private_fields.applicable_kinds = field
-dotnet_naming_symbols.private_fields.applicable_accessibilities = private
-dotnet_naming_style.prefix_underscore.capitalization = camel_case
-dotnet_naming_style.prefix_underscore.required_prefix = _
-
-
-# Local variables must be camelCase
-# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md
-dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local
-dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local
-dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group
-dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style
-dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.severity = silent
-
-# This rule should never fire. However, it's included for at least two purposes:
-# First, it helps to understand, reason about, and root-case certain types of issues, such as bugs in .editorconfig parsers.
-# Second, it helps to raise immediate awareness if a new field type is added (as occurred recently in C#).
-dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_accessibilities = *
-dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_kinds = field
-dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols = sanity_check_uncovered_field_case_group
-dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style = internal_error_style
-dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity = error
-
-##########################################
-# VSThread
-##########################################
-dotnet_diagnostic.VSTHRD111.severity = none
-
-
-##########################################
-# Other Naming Rules
-##########################################
-
-# All of the following must be PascalCase:
-# - Namespaces
-# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-namespaces
-# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
-# - Classes and Enumerations
-# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
-# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md
-# - Delegates
-# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces#names-of-common-types
-# - Constructors, Properties, Events, Methods
-# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-type-members
-dotnet_naming_symbols.element_group.applicable_kinds = namespace, class, enum, struct, delegate, event, method, property
-dotnet_naming_rule.element_rule.symbols = element_group
-dotnet_naming_rule.element_rule.style = pascal_case_style
-dotnet_naming_rule.element_rule.severity = warning
-
-# Interfaces use PascalCase and are prefixed with uppercase 'I'
-# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
-dotnet_naming_symbols.interface_group.applicable_kinds = interface
-dotnet_naming_rule.interface_rule.symbols = interface_group
-dotnet_naming_rule.interface_rule.style = prefix_interface_with_i_style
-dotnet_naming_rule.interface_rule.severity = warning
-
-# Generics Type Parameters use PascalCase and are prefixed with uppercase 'T'
-# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces
-dotnet_naming_symbols.type_parameter_group.applicable_kinds = type_parameter
-dotnet_naming_rule.type_parameter_rule.symbols = type_parameter_group
-dotnet_naming_rule.type_parameter_rule.style = prefix_type_parameters_with_t_style
-dotnet_naming_rule.type_parameter_rule.severity = warning
-
-# Function parameters use camelCase
-# https://docs.microsoft.com/dotnet/standard/design-guidelines/naming-parameters
-dotnet_naming_symbols.parameters_group.applicable_kinds = parameter
-dotnet_naming_rule.parameters_rule.symbols = parameters_group
-dotnet_naming_rule.parameters_rule.style = camel_case_style
-dotnet_naming_rule.parameters_rule.severity = warning
\ No newline at end of file
+# Generic type parameter documentation should have text.
+dotnet_diagnostic.sa1622.severity = None
+
+# XML comment analysis is disabled due to project configuration
+dotnet_diagnostic.sa0001.severity = None
+
+# The file header is missing or not located at the top of the file
+dotnet_diagnostic.sa1633.severity = None
+
+# Use string.Empty for empty strings
+dotnet_diagnostic.sa1122.severity = None
+
+# Variable '_' should begin with lower-case letter
+dotnet_diagnostic.sa1312.severity = None
+
+# Parameter '_' should begin with lower-case letter
+dotnet_diagnostic.sa1313.severity = None
+
+# Elements should be documented
+dotnet_diagnostic.sa1600.severity = None
+
+# Prefix local calls with this
+dotnet_diagnostic.sa1101.severity = None
+
+# 'public' members should come before 'private' members
+dotnet_diagnostic.sa1202.severity = None
+
+# Comments should contain text
+dotnet_diagnostic.sa1120.severity = None
+
+# Constant fields should appear before non-constant fields
+dotnet_diagnostic.sa1203.severity = None
+
+# Field '_blah' should not begin with an underscore
+dotnet_diagnostic.sa1309.severity = None
+
+# Use trailing comma in multi-line initializers
+dotnet_diagnostic.sa1413.severity = None
+
+# A method should not follow a class
+dotnet_diagnostic.sa1201.severity = None
+
+# Elements should be separated by blank line
+dotnet_diagnostic.sa1516.severity = None
+
+# The parameter spans multiple lines
+dotnet_diagnostic.sa1118.severity = None
+
+# Static members should appear before non-static members
+dotnet_diagnostic.sa1204.severity = None
+
+# Put constructor initializers on their own line
+dotnet_diagnostic.sa1128.severity = None
+
+# Opening braces should not be preceded by blank line
+dotnet_diagnostic.sa1509.severity = None
+
+# The parameter should begin on the line after the previous parameter
+dotnet_diagnostic.sa1115.severity = None
+
+# File name should match first type name
+dotnet_diagnostic.sa1649.severity = None
+
+# File may only contain a single type
+dotnet_diagnostic.sa1402.severity = None
+
+# Enumeration items should be documented
+dotnet_diagnostic.sa1602.severity = None
+
+# Element should not be on a single line
+dotnet_diagnostic.sa1502.severity = None
+
+# Closing parenthesis should not be preceded by a space
+dotnet_diagnostic.sa1009.severity = None
+
+# Closing parenthesis should be on line of last parameter
+dotnet_diagnostic.sa1111.severity = None
+
+# Braces should not be ommitted
+dotnet_diagnostic.sa1503.severity = None
+
+dotnet_diagnostic.sa1401.severity = None
+
+# The parameters to a C# method or indexer call or declaration are not all on the same line or each on a separate line.
+# dotnet_diagnostic.SA1117.severity = Suggestion
+
+# The parameters to a C# method or indexer call or declaration span across multiple lines, but the first parameter does not start on the line after the opening bracket.
+# dotnet_diagnostic.SA1116.severity = Suggestion
+
+# A C# partial element is missing a documentation header.
+dotnet_diagnostic.sa1601.severity = None
+
+# A tag within a C# element’s documentation header is empty.
+dotnet_diagnostic.sa1614.severity = None
+
+# A C# element is missing documentation for its return value.
+dotnet_diagnostic.sa1615.severity = None
+
+# The tag within a C# element’s documentation header is empty.
+dotnet_diagnostic.sa1616.severity = None
+
+# An opening brace within a C# element is not spaced correctly.
+dotnet_diagnostic.sa1012.severity = Suggestion
+
+# A closing brace within a C# element is not spaced correctly.
+dotnet_diagnostic.sa1013.severity = Suggestion
+
+# A call to an instance member of the local class or a base class is not prefixed with 'this.', within a C# code file.
+dotnet_diagnostic.sa1101.severity = None
+
+# The keywords within the declaration of an element do not follow a standard ordering scheme.
+dotnet_diagnostic.SA1206.severity = None
+
+# A single-line comment within C# code is not preceded by a blank line.
+dotnet_diagnostic.SA1515.severity = Suggestion
+
+##################################################################################
+## https://github.com/meziantou/Meziantou.Analyzer/tree/main/docs
+## Meziantou.Analyzer
+
+# MA0049: Type name should not match containing namespace
+dotnet_diagnostic.ma0049.severity = Suggestion
+
+# MA0048: File name must match type name
+dotnet_diagnostic.ma0048.severity = Suggestion
+
+# MA0051: Method is too long
+dotnet_diagnostic.ma0051.severity = Suggestion
+
+# https://www.meziantou.net/string-comparisons-are-harder-than-it-seems.htm
+# MA0006 - Use String.Equals instead of equality operator
+dotnet_diagnostic.ma0006.severity = Suggestion
+
+# MA0002 - IEqualityComparer or IComparer is missing
+dotnet_diagnostic.ma0002.severity = Suggestion
+
+# MA0001 - StringComparison is missing
+dotnet_diagnostic.ma0001.severity = Suggestion
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#13-pass-cancellation-token
+# MA0040: Specify a cancellation token
+dotnet_diagnostic.ma0032.severity = Suggestion
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#13-pass-cancellation-token
+# MA0040: Flow the cancellation token when available
+dotnet_diagnostic.ma0040.severity = Suggestion
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#14-using-cancellation-token-with-iasyncenumerable
+# MA0079: Use a cancellation token using .WithCancellation()
+dotnet_diagnostic.ma0079.severity = Suggestion
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#14-using-cancellation-token-with-iasyncenumerable
+# MA0080: Use a cancellation token using .WithCancellation()
+dotnet_diagnostic.ma0080.severity = Suggestion
+
+# Use Task.ConfigureAwait(false) as the current SynchronizationContext is not needed
+dotnet_diagnostic.MA0004.severity = none
+
+# Add regex evaluation timeout
+dotnet_diagnostic.MA0009.severity = none
+
+# Use an overload of 'ToString' that has a 'System.IFormatProvider' parameter. Already caught by CA1305.
+dotnet_diagnostic.MA0011.severity = none
+
+# Use an overload of 'System.ArgumentException' with the parameter name. Just a suggestion since we have a bunch of justified exceptions.
+dotnet_diagnostic.MA0015.severity = suggestion
+
+# Use an explicit StringComparer to compute hash codes
+dotnet_diagnostic.MA0021.severity = none
+
+# Declare types in namespaces. Already caught by CA1050
+dotnet_diagnostic.MA0047.severity = none
+
+# Use an overload of 'GetHashCode' that has a StringComparison parameter
+dotnet_diagnostic.MA0074.severity = none
+
+##################################################################################
+## http://pihrt.net/Roslynator/Analyzers
+## http://pihrt.net/Roslynator/Refactorings
+## https://github.com/JosefPihrt/Roslynator/blob/main/docs/Configuration.md
+## Roslynator
+
+# RCS1036 - Remove redundant empty line.
+dotnet_diagnostic.rcs1036.severity = None
+
+# RCS1037 - Remove trailing white-space.
+dotnet_diagnostic.rcs1037.severity = None
+
+# RCS1194: Implement exception constructors
+dotnet_diagnostic.rcs1194.severity = None
+
+# https://cezarypiatek.github.io/post/async-analyzers-p1/#1-redundant-asyncawait
+# RCS1174: Remove redundant async/await.
+dotnet_diagnostic.rcs1174.severity = error
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#10-returning-null-from-a-task-returning-method
+# RCS1210: Return Task.FromResult instead of returning null.
+dotnet_diagnostic.rcs1210.severity = error
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#9-missing-configureawaitbool
+# RCS1090: Call 'ConfigureAwait(false)'.
+dotnet_diagnostic.rcs1090.severity = Suggestion
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#11-asynchronous-method-names-should-end-with-async
+#RCS1046: Asynchronous method name should end with 'Async'.
+dotnet_diagnostic.rcs1046.severity = Suggestion
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#12-non-asynchronous-method-names-shouldnt-end-with-async
+# RCS1047: Non-asynchronous method name should not end with 'Async'.
+dotnet_diagnostic.rcs1047.severity = error
+
+# https://github.com/JosefPihrt/Roslynator/blob/master/docs/analyzers/RCS1174.md
+# RCS1174: Remove redundant async/await
+dotnet_diagnostic.rcs1174.severity = Suggestion
+
+
+# Combine 'Enumerable.Where' method chain. It doesn't make it more readable in all cases.
+dotnet_diagnostic.RCS1112.severity = suggestion
+
+# Inline local variable.
+dotnet_diagnostic.RCS1124.severity = suggestion
+
+# Add exception to documentation comment. Nice suggestion, but we don't want to document exceptions for internal code.
+dotnet_diagnostic.RCS1140.severity = suggestion
+
+# Missing documentation
+dotnet_diagnostic.RCS1141.severity = suggestion
+dotnet_diagnostic.RCS1142.severity = suggestion
+
+# Use conditional access. Suggestion because it doesn't always improve readability
+dotnet_diagnostic.RCS1146.severity = suggestion
+
+# Enum should declare explicit values. Disabled because we're not storing them.
+dotnet_diagnostic.RCS1161.severity = none
+
+# Static member in generic type should use a type parameter. Disabled because it's not always applicable.
+dotnet_diagnostic.RCS1158.severity = none
+
+# Add region name to #endregion.
+dotnet_diagnostic.RCS1189.severity = none
+
+# Convert comment to documentation comment. Disabled because it also complains about SMELL/REFACTOR comments
+dotnet_diagnostic.RCS1181.severity = none
+
+# Use Regex instance instead of static method. Disabled because it's not always worth it.
+dotnet_diagnostic.RCS1186.severity = none
+
+# Use bit shift operator.
+dotnet_diagnostic.RCS1237.severity = none
+
+# RCS1228: Unused element in documentation comment. (Equivalent to SA1614)
+dotnet_diagnostic.RCS1228.severity = suggestion
+
+##################################################################################
+## https://github.com/microsoft/vs-threading
+## Microsoft.VisualStudio.Threading.Analyzers
+##################################################################################
+
+# https://cezarypiatek.github.io/post/async-analyzers-p1/#2-calling-synchronous-method-inside-the-async-method
+# VSTHRD103: Call async methods when in an async method
+dotnet_diagnostic.vsthrd103.severity = Suggestion
+
+
+# https://cezarypiatek.github.io/post/async-analyzers-p1/#3-async-void-method
+# VSTHRD100: Avoid async void methods
+dotnet_diagnostic.vsthrd100.severity = error
+
+# https://cezarypiatek.github.io/post/async-analyzers-p1/#4-unsupported-async-delegates
+# VSTHRD101: Avoid unsupported async delegates
+dotnet_diagnostic.vsthrd101.severity = error
+
+# https://cezarypiatek.github.io/post/async-analyzers-p1/#5-not-awaited-task-within-using-expression
+# VSTHRD107: Await Task within using expression
+dotnet_diagnostic.vsthrd107.severity = error
+
+# https://cezarypiatek.github.io/post/async-analyzers-p1/#7-unobserved-result-of-asynchronous-method
+# VSTHRD110: Observe result of async calls
+dotnet_diagnostic.vsthrd110.severity = Suggestion
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#8-synchronous-waits
+# VSTHRD002: Avoid problematic synchronous waits
+dotnet_diagnostic.vsthrd002.severity = Suggestion
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#9-missing-configureawaitbool
+# VSTHRD111: Use ConfigureAwait(bool)
+dotnet_diagnostic.vsthrd111.severity = Suggestion
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#10-returning-null-from-a-task-returning-method
+# VSTHRD114: Avoid returning a null Task
+dotnet_diagnostic.vsthrd114.severity = error
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#11-asynchronous-method-names-should-end-with-async
+# VSTHRD200: Use "Async" suffix for async methods
+dotnet_diagnostic.vsthrd200.severity = Suggestion
+
+# https://cezarypiatek.github.io/post/async-analyzers-p2/#12-non-asynchronous-method-names-shouldnt-end-with-async
+# VSTHRD200: Use "Async" suffix for async methods
+dotnet_diagnostic.vsthrd200.severity = Suggestion
diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml
index 066d207c..1422499f 100644
--- a/.github/actions/build/action.yml
+++ b/.github/actions/build/action.yml
@@ -50,6 +50,18 @@ runs:
# restore root solution
run: dotnet restore
+ # npm install, runs `prepare` script automatically in the initialize step
+ - name: Install NPM Dependencies
+ shell: bash
+ if: success()
+ run: npm install
+
+ - name: Format Service
+ shell: bash
+ if: ${{ success()}}
+ run: |
+ npm run ci-format
+
- name: Build Service
shell: bash
if: ${{ success()}}
diff --git a/Directory.Build.props b/Directory.Build.props
index 50b29207..dcca6505 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -39,7 +39,9 @@
true
true
- All
+ false
+ latest-Recommended
+ Recommended
diff --git a/README.md b/README.md
index f897c653..b40dd661 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,8 @@
- [Structure of Project](#structure-of-project)
- [Development Setup](#development-setup)
- [Dotnet Tools Packages](#dotnet-tools-packages)
+ - [Husky](#husky)
+ - [Upgrade Nuget Packages](#upgrade-nuget-packages)
- [How to Run](#how-to-run)
- [Config Certificate](#config-certificate)
- [Docker Compose](#docker-compose)
@@ -47,7 +49,7 @@
- :sparkle: Using `Postgres` for `write side` of some microservices.
- :sparkle: Using `MongoDB` for `read side` of some microservices.
- :sparkle: Using `Event Store` for `write side` of Booking-Microservice to store all `historical state` of aggregate.
-- :sparkle: Using `Inbox Pattern` for ensuring message idempotency for receiver and `Exactly once Delivery`.
+- :sparkle: Using `Inbox Pattern` for ensuring message idempotency for receiver and `Exactly once Delivery`.
- :sparkle: Using `Outbox Pattern` for ensuring no message is lost and there is at `At Least One Delivery`.
- :sparkle: Using `Unit Testing` for testing small units and mocking our dependencies with `Nsubstitute`.
- :sparkle: Using `End-To-End Testing` and `Integration Testing` for testing `features` with all dependencies using `testcontainers`.
@@ -159,7 +161,7 @@ Using the CQRS pattern, we cut each business functionality into vertical slices,
## Development Setup
### Dotnet Tools Packages
-For installing our requirement package with .NET cli tools, we need to install `dotnet tool manifest`.
+For installing our requirement packages with .NET cli tools, we need to install `dotnet tool manifest`.
```bash
dotnet new tool-manifest
```
@@ -168,6 +170,24 @@ And after that we can restore our dotnet tools packages with .NET cli tools from
dotnet tool restore
```
+### Husky
+Here we use `husky` to handel some pre commit rules and we used `conventional commits` rules and `formatting` as pre commit rules, here in [package.json](./package.json). of course, we can add more rules for pre commit in future. (find more about husky in the [documentation](https://typicode.github.io/husky/get-started.html))
+We need to install `husky` package for `manage` `pre commits hooks` and also I add two packages `@commitlint/cli` and `@commitlint/config-conventional` for handling conventional commits rules in [package.json](./package.json).
+Run the command bellow in the root of project to install all npm dependencies related to husky:
+
+```bash
+npm install
+```
+
+> Note: In the root of project we have `.husky` folder and it has `commit-msg` file for handling conventional commits rules with provide user friendly message and `pre-commit` file that we can run our `scripts` as a `pre-commit` hooks. that here we call `format` script from [package.json](./package.json) for formatting purpose.
+
+### Upgrade Nuget Packages
+For upgrading our nuget packages to last version, we use the great package [dotnet-outdated](https://github.com/dotnet-outdated/dotnet-outdated).
+Run the command below in the root of project to upgrade all of packages to last version:
+```bash
+dotnet outdated -u
+```
+
## How to Run
> ### Config Certificate
diff --git a/package.json b/package.json
index f9e4d252..7ca936f2 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,7 @@
"scripts": {
"prepare": "husky && dotnet tool restore",
"format": "dotnet format booking-microservices-sample.sln --severity error --verbosity detailed",
+ "ci-format": "dotnet format booking-microservices-sample.sln --verify-no-changes --severity error --verbosity detailed",
"upgrade-packages": "dotnet outdated --upgrade"
},
"devDependencies": {
diff --git a/src/BuildingBlocks/BuildingBlocks.csproj b/src/BuildingBlocks/BuildingBlocks.csproj
index 2e403685..59523cd8 100644
--- a/src/BuildingBlocks/BuildingBlocks.csproj
+++ b/src/BuildingBlocks/BuildingBlocks.csproj
@@ -18,7 +18,7 @@
-
+
@@ -51,7 +51,7 @@
-
+
diff --git a/src/BuildingBlocks/Core/EventDispatcher.cs b/src/BuildingBlocks/Core/EventDispatcher.cs
index 56daa4c7..36f278c0 100644
--- a/src/BuildingBlocks/Core/EventDispatcher.cs
+++ b/src/BuildingBlocks/Core/EventDispatcher.cs
@@ -54,13 +54,13 @@ await _persistMessageProcessor.PublishMessageAsync(
switch (events)
{
case IReadOnlyList domainEvents:
- {
- var integrationEvents = await MapDomainEventToIntegrationEventAsync(domainEvents)
+ {
+ var integrationEvents = await MapDomainEventToIntegrationEventAsync(domainEvents)
.ConfigureAwait(false);
- await PublishIntegrationEvent(integrationEvents);
- break;
- }
+ await PublishIntegrationEvent(integrationEvents);
+ break;
+ }
case IReadOnlyList integrationEvents:
await PublishIntegrationEvent(integrationEvents);
diff --git a/src/BuildingBlocks/EFCore/Extensions.cs b/src/BuildingBlocks/EFCore/Extensions.cs
index 497ffbd5..11a21a87 100644
--- a/src/BuildingBlocks/EFCore/Extensions.cs
+++ b/src/BuildingBlocks/EFCore/Extensions.cs
@@ -16,36 +16,40 @@ namespace BuildingBlocks.EFCore;
public static class Extensions
{
- public static IServiceCollection AddCustomDbContext(
- this IServiceCollection services)
- where TContext : DbContext, IDbContext
+ public static IServiceCollection AddCustomDbContext(this IServiceCollection services)
+ where TContext : DbContext, IDbContext
{
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
services.AddValidateOptions();
- services.AddDbContext((sp, options) =>
- {
- var postgresOptions = sp.GetRequiredService();
+ services.AddDbContext(
+ (sp, options) =>
+ {
+ var postgresOptions = sp.GetRequiredService();
- Guard.Against.Null(options, nameof(postgresOptions));
+ Guard.Against.Null(options, nameof(postgresOptions));
- options.UseNpgsql(postgresOptions?.ConnectionString,
- dbOptions =>
- {
- dbOptions.MigrationsAssembly(typeof(TContext).Assembly.GetName().Name);
- })
- // https://github.com/efcore/EFCore.NamingConventions
- .UseSnakeCaseNamingConvention();
- });
+ options.UseNpgsql(
+ postgresOptions?.ConnectionString,
+ dbOptions =>
+ {
+ dbOptions.MigrationsAssembly(typeof(TContext).Assembly.GetName().Name);
+ })
+ // https://github.com/efcore/EFCore.NamingConventions
+ .UseSnakeCaseNamingConvention();
+ });
services.AddScoped(provider => provider.GetService());
return services;
}
- public static IApplicationBuilder UseMigration(this IApplicationBuilder app, IWebHostEnvironment env)
- where TContext : DbContext, IDbContext
+ public static IApplicationBuilder UseMigration(
+ this IApplicationBuilder app,
+ IWebHostEnvironment env
+ )
+ where TContext : DbContext, IDbContext
{
MigrateDatabaseAsync(app.ApplicationServices).GetAwaiter().GetResult();
@@ -62,13 +66,16 @@ public static IApplicationBuilder UseMigration(this IApplicationBuilde
public static void FilterSoftDeletedProperties(this ModelBuilder modelBuilder)
{
Expression> filterExpr = e => !e.IsDeleted;
+
foreach (var mutableEntityType in modelBuilder.Model.GetEntityTypes()
.Where(m => m.ClrType.IsAssignableTo(typeof(IEntity))))
{
// modify expression to handle correct child type
var parameter = Expression.Parameter(mutableEntityType.ClrType);
+
var body = ReplacingExpressionVisitor
.Replace(filterExpr.Parameters.First(), parameter, filterExpr.Body);
+
var lambdaExpression = Expression.Lambda(body, parameter);
// set filter
@@ -76,8 +83,7 @@ public static void FilterSoftDeletedProperties(this ModelBuilder modelBuilder)
}
}
-
- //ref: https://andrewlock.net/customising-asp-net-core-identity-ef-core-naming-conventions-for-postgresql/
+ // ref: https://andrewlock.net/customising-asp-net-core-identity-ef-core-naming-conventions-for-postgresql/
public static void ToSnakeCaseTables(this ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes())
@@ -86,7 +92,9 @@ public static void ToSnakeCaseTables(this ModelBuilder modelBuilder)
entity.SetTableName(entity.GetTableName()?.Underscore());
var tableObjectIdentifier =
- StoreObjectIdentifier.Table(entity.GetTableName()?.Underscore()!, entity.GetSchema());
+ StoreObjectIdentifier.Table(
+ entity.GetTableName()?.Underscore()!,
+ entity.GetSchema());
// Replace column names
foreach (var property in entity.GetProperties())
@@ -107,7 +115,7 @@ public static void ToSnakeCaseTables(this ModelBuilder modelBuilder)
}
private static async Task MigrateDatabaseAsync(IServiceProvider serviceProvider)
- where TContext : DbContext, IDbContext
+ where TContext : DbContext, IDbContext
{
using var scope = serviceProvider.CreateScope();
@@ -119,6 +127,7 @@ private static async Task SeedDataAsync(IServiceProvider serviceProvider)
{
using var scope = serviceProvider.CreateScope();
var seeders = scope.ServiceProvider.GetServices();
+
foreach (var seeder in seeders)
{
await seeder.SeedAllAsync();
diff --git a/src/BuildingBlocks/EventStoreDB/Events/EventTypeMapper.cs b/src/BuildingBlocks/EventStoreDB/Events/EventTypeMapper.cs
index d8dbe8d5..28d2b3c8 100644
--- a/src/BuildingBlocks/EventStoreDB/Events/EventTypeMapper.cs
+++ b/src/BuildingBlocks/EventStoreDB/Events/EventTypeMapper.cs
@@ -22,7 +22,7 @@ public static void AddCustomMap(Type eventType, string mappedEventTypeName)
public static string ToName(Type eventType) => Instance.typeNameMap.GetOrAdd(eventType, _ =>
{
- var eventTypeName = eventType.FullName!.Replace(".", "_");
+ var eventTypeName = eventType.FullName!.Replace(".", "_", StringComparison.CurrentCulture);
Instance.typeMap.AddOrUpdate(eventTypeName, eventType, (_, _) => eventType);
@@ -31,7 +31,7 @@ public static string ToName(Type eventType) => Instance.typeNameMap.GetOrAdd(eve
public static Type? ToType(string eventTypeName) => Instance.typeMap.GetOrAdd(eventTypeName, _ =>
{
- var type = TypeProvider.GetFirstMatchingTypeFromCurrentDomainAssembly(eventTypeName.Replace("_", "."));
+ var type = TypeProvider.GetFirstMatchingTypeFromCurrentDomainAssembly(eventTypeName.Replace("_", ".", StringComparison.CurrentCulture));
if (type == null)
return null;
diff --git a/src/BuildingBlocks/Jwt/AuthHeaderHandler.cs b/src/BuildingBlocks/Jwt/AuthHeaderHandler.cs
index 754cee82..ec4de799 100644
--- a/src/BuildingBlocks/Jwt/AuthHeaderHandler.cs
+++ b/src/BuildingBlocks/Jwt/AuthHeaderHandler.cs
@@ -17,7 +17,7 @@ protected override Task SendAsync(HttpRequestMessage reques
{
var token = (_httpContext?.HttpContext?.Request.Headers["Authorization"])?.ToString();
- request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token?.Replace("Bearer ", ""));
+ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token?.Replace("Bearer ", "", StringComparison.CurrentCulture));
return base.SendAsync(request, cancellationToken);
}
diff --git a/src/BuildingBlocks/Logging/Extensions.cs b/src/BuildingBlocks/Logging/Extensions.cs
index b0cb4913..ed1813eb 100644
--- a/src/BuildingBlocks/Logging/Extensions.cs
+++ b/src/BuildingBlocks/Logging/Extensions.cs
@@ -1,3 +1,4 @@
+using System.Globalization;
using System.Text;
using BuildingBlocks.Web;
using Microsoft.AspNetCore.Builder;
@@ -44,7 +45,7 @@ public static WebApplicationBuilder AddCustomSerilog(this WebApplicationBuilder
new ElasticsearchSinkOptions(new Uri(logOptions.Elastic.ElasticServiceUrl))
{
AutoRegisterTemplate = true,
- IndexFormat = $"{appOptions.Name}-{environment?.ToLower()}"
+ IndexFormat = $"{appOptions.Name}-{environment?.ToLower(CultureInfo.CurrentCulture)}"
});
}
diff --git a/src/BuildingBlocks/Mongo/ImmutablePocoConvention.cs b/src/BuildingBlocks/Mongo/ImmutablePocoConvention.cs
index 55d52221..7052d41c 100644
--- a/src/BuildingBlocks/Mongo/ImmutablePocoConvention.cs
+++ b/src/BuildingBlocks/Mongo/ImmutablePocoConvention.cs
@@ -67,7 +67,7 @@ private static List GetMatchingProperties(
private static bool ParameterMatchProperty(ParameterInfo parameter, PropertyInfo property)
{
- return string.Equals(property.Name, parameter.Name, System.StringComparison.InvariantCultureIgnoreCase)
+ return string.Equals(property.Name, parameter.Name, StringComparison.OrdinalIgnoreCase)
&& parameter.ParameterType == property.PropertyType;
}
diff --git a/src/BuildingBlocks/Mongo/MongoDbContext.cs b/src/BuildingBlocks/Mongo/MongoDbContext.cs
index 4ef4e5ba..fbbce103 100644
--- a/src/BuildingBlocks/Mongo/MongoDbContext.cs
+++ b/src/BuildingBlocks/Mongo/MongoDbContext.cs
@@ -1,3 +1,4 @@
+using System.Globalization;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Conventions;
@@ -42,7 +43,7 @@ private static void RegisterConventions()
public IMongoCollection GetCollection(string? name = null)
{
- return Database.GetCollection(name ?? typeof(T).Name.ToLower());
+ return Database.GetCollection(name ?? typeof(T).Name.ToLower(CultureInfo.CurrentCulture));
}
public void Dispose()
diff --git a/src/BuildingBlocks/TestBase/TestBase.cs b/src/BuildingBlocks/TestBase/TestBase.cs
index cfc33dbe..a339b814 100644
--- a/src/BuildingBlocks/TestBase/TestBase.cs
+++ b/src/BuildingBlocks/TestBase/TestBase.cs
@@ -37,7 +37,7 @@ namespace BuildingBlocks.TestBase;
using Testcontainers.RabbitMq;
public class TestFixture : IAsyncLifetime
- where TEntryPoint : class
+where TEntryPoint : class
{
private readonly WebApplicationFactory _factory;
private int Timeout => 120; // Second
@@ -60,10 +60,11 @@ public HttpClient HttpClient
var claims =
new Dictionary
{
- { ClaimTypes.Name, "test@sample.com" },
- { ClaimTypes.Role, "admin" },
+ {ClaimTypes.Name, "test@sample.com"},
+ {ClaimTypes.Role, "admin"},
{"scope", "flight-api"}
};
+
var httpClient = _factory?.CreateClient();
httpClient.SetFakeBearerToken(claims);
return httpClient;
@@ -71,7 +72,9 @@ public HttpClient HttpClient
}
public GrpcChannel Channel =>
- GrpcChannel.ForAddress(HttpClient.BaseAddress!, new GrpcChannelOptions { HttpClient = HttpClient });
+ GrpcChannel.ForAddress(
+ HttpClient.BaseAddress!,
+ new GrpcChannelOptions { HttpClient = HttpClient });
public IServiceProvider ServiceProvider => _factory?.Services;
public IConfiguration Configuration => _factory?.Services.GetRequiredService();
@@ -80,28 +83,36 @@ public HttpClient HttpClient
protected TestFixture()
{
_factory = new WebApplicationFactory()
- .WithWebHostBuilder(builder =>
- {
- builder.ConfigureAppConfiguration(AddCustomAppSettings);
-
- builder.UseEnvironment("test");
- builder.ConfigureServices(services =>
+ .WithWebHostBuilder(
+ builder =>
{
- TestRegistrationServices?.Invoke(services);
- services.ReplaceSingleton(AddHttpContextAccessorMock);
-
- services.AddSingleton();
-
- // add authentication using a fake jwt bearer - we can use SetAdminUser method to set authenticate user to existing HttContextAccessor
- // https://github.com/webmotions/fake-authentication-jwtbearer
- // https://github.com/webmotions/fake-authentication-jwtbearer/issues/14
- services.AddAuthentication(options =>
- {
- options.DefaultAuthenticateScheme = FakeJwtBearerDefaults.AuthenticationScheme;
- options.DefaultChallengeScheme = FakeJwtBearerDefaults.AuthenticationScheme;
- }).AddFakeJwtBearer();
+ builder.ConfigureAppConfiguration(AddCustomAppSettings);
+
+ builder.UseEnvironment("test");
+
+ builder.ConfigureServices(
+ services =>
+ {
+ TestRegistrationServices?.Invoke(services);
+ services.ReplaceSingleton(AddHttpContextAccessorMock);
+
+ services.AddSingleton();
+
+ // add authentication using a fake jwt bearer - we can use SetAdminUser method to set authenticate user to existing HttContextAccessor
+ // https://github.com/webmotions/fake-authentication-jwtbearer
+ // https://github.com/webmotions/fake-authentication-jwtbearer/issues/14
+ services.AddAuthentication(
+ options =>
+ {
+ options.DefaultAuthenticateScheme =
+ FakeJwtBearerDefaults.AuthenticationScheme;
+
+ options.DefaultChallengeScheme =
+ FakeJwtBearerDefaults.AuthenticationScheme;
+ })
+ .AddFakeJwtBearer();
+ });
});
- });
}
public async Task InitializeAsync()
@@ -114,7 +125,7 @@ public async Task DisposeAsync()
{
await StopTestContainerAsync();
await _factory.DisposeAsync();
- CancellationTokenSource.Cancel();
+ await CancellationTokenSource.CancelAsync();
}
public virtual void RegisterServices(Action services)
@@ -153,87 +164,123 @@ protected async Task ExecuteScopeAsync(Func> act
public Task SendAsync(IRequest request)
{
- return ExecuteScopeAsync(sp =>
- {
- var mediator = sp.GetRequiredService();
+ return ExecuteScopeAsync(
+ sp =>
+ {
+ var mediator = sp.GetRequiredService();
- return mediator.Send(request);
- });
+ return mediator.Send(request);
+ });
}
public Task SendAsync(IRequest request)
{
- return ExecuteScopeAsync(sp =>
- {
- var mediator = sp.GetRequiredService();
- return mediator.Send(request);
- });
+ return ExecuteScopeAsync(
+ sp =>
+ {
+ var mediator = sp.GetRequiredService();
+ return mediator.Send(request);
+ });
}
- public async Task Publish(TMessage message, CancellationToken cancellationToken = default)
- where TMessage : class, IEvent
+ public async Task Publish(
+ TMessage message,
+ CancellationToken cancellationToken = default
+ )
+ where TMessage : class, IEvent
{
await TestHarness.Bus.Publish(message, cancellationToken);
}
- public async Task WaitForPublishing(CancellationToken cancellationToken = default)
- where TMessage : class, IEvent
+ public async Task WaitForPublishing(
+ CancellationToken cancellationToken = default
+ )
+ where TMessage : class, IEvent
{
- var result = await WaitUntilConditionMet(async () =>
- {
- var published = await TestHarness.Published.Any(cancellationToken);
- var faulty = await TestHarness.Published.Any>(cancellationToken);
- return published && faulty == false;
- });
- return result;
- }
+ var result = await WaitUntilConditionMet(
+ async () =>
+ {
+ var published =
+ await TestHarness.Published.Any(cancellationToken);
- public async Task WaitForConsuming(CancellationToken cancellationToken = default)
- where TMessage : class, IEvent
- {
- var result = await WaitUntilConditionMet(async () =>
- {
- var consumed = await TestHarness.Consumed.Any(cancellationToken);
- var faulty = await TestHarness.Consumed.Any>(cancellationToken);
+ var faulty =
+ await TestHarness.Published.Any>(
+ cancellationToken);
- return consumed && faulty == false;
- });
+ return published && faulty == false;
+ });
return result;
}
- public async Task ShouldProcessedPersistInternalCommand(
- CancellationToken cancellationToken = default)
- where TInternalCommand : class, IInternalCommand
+ public async Task WaitForConsuming(
+ CancellationToken cancellationToken = default
+ )
+ where TMessage : class, IEvent
{
- var result = await WaitUntilConditionMet(async () =>
- {
- return await ExecuteScopeAsync(async sp =>
- {
- var persistMessageProcessor = sp.GetService();
- Guard.Against.Null(persistMessageProcessor, nameof(persistMessageProcessor));
+ var result = await WaitUntilConditionMet(
+ async () =>
+ {
+ var consumed =
+ await TestHarness.Consumed.Any(cancellationToken);
- var filter = await persistMessageProcessor.GetByFilterAsync(x =>
- x.DeliveryType == MessageDeliveryType.Internal &&
- typeof(TInternalCommand).ToString() == x.DataType);
+ var faulty =
+ await TestHarness.Consumed.Any>(cancellationToken);
- var res = filter.Any(x => x.MessageStatus == MessageStatus.Processed);
+ return consumed && faulty == false;
+ });
- return res;
- });
- });
+ return result;
+ }
+
+ public async Task ShouldProcessedPersistInternalCommand(
+ CancellationToken cancellationToken = default
+ )
+ where TInternalCommand : class, IInternalCommand
+ {
+ var result = await WaitUntilConditionMet(
+ async () =>
+ {
+ return await ExecuteScopeAsync(
+ async sp =>
+ {
+ var persistMessageProcessor =
+ sp.GetService();
+
+ Guard.Against.Null(
+ persistMessageProcessor,
+ nameof(persistMessageProcessor));
+
+ var filter =
+ await persistMessageProcessor.GetByFilterAsync(
+ x =>
+ x.DeliveryType ==
+ MessageDeliveryType.Internal &&
+ typeof(TInternalCommand).ToString() ==
+ x.DataType);
+
+ var res = filter.Any(
+ x => x.MessageStatus == MessageStatus.Processed);
+
+ return res;
+ });
+ });
return result;
}
// Ref: https://tech.energyhelpline.com/in-memory-testing-with-masstransit/
- private async Task WaitUntilConditionMet(Func> conditionToMet, int? timeoutSecond = null)
+ private async Task WaitUntilConditionMet(
+ Func> conditionToMet,
+ int? timeoutSecond = null
+ )
{
var time = timeoutSecond ?? Timeout;
var startTime = DateTime.Now;
var timeoutExpired = false;
var meet = await conditionToMet.Invoke();
+
while (!meet)
{
if (timeoutExpired)
@@ -275,27 +322,42 @@ private async Task StopTestContainerAsync()
private void AddCustomAppSettings(IConfigurationBuilder configuration)
{
- configuration.AddInMemoryCollection(new KeyValuePair[]
- {
- new("PostgresOptions:ConnectionString", PostgresTestcontainer.GetConnectionString()),
- new("PersistMessageOptions:ConnectionString", PostgresPersistTestContainer.GetConnectionString()),
- new("RabbitMqOptions:HostName", RabbitMqTestContainer.Hostname),
- new("RabbitMqOptions:UserName", TestContainers.RabbitMqContainerConfiguration.UserName),
- new("RabbitMqOptions:Password", TestContainers.RabbitMqContainerConfiguration.Password), new(
- "RabbitMqOptions:Port",
- RabbitMqTestContainer.GetMappedPublicPort(TestContainers.RabbitMqContainerConfiguration.Port)
- .ToString(NumberFormatInfo.InvariantInfo)),
- new("MongoOptions:ConnectionString", MongoDbTestContainer.GetConnectionString()),
- new("MongoOptions:DatabaseName", TestContainers.MongoContainerConfiguration.Name),
- new("EventStoreOptions:ConnectionString", EventStoreDbTestContainer.GetConnectionString())
- });
+ configuration.AddInMemoryCollection(
+ new KeyValuePair[]
+ {
+ new(
+ "PostgresOptions:ConnectionString",
+ PostgresTestcontainer.GetConnectionString()),
+ new(
+ "PersistMessageOptions:ConnectionString",
+ PostgresPersistTestContainer.GetConnectionString()),
+ new("RabbitMqOptions:HostName", RabbitMqTestContainer.Hostname),
+ new(
+ "RabbitMqOptions:UserName",
+ TestContainers.RabbitMqContainerConfiguration.UserName),
+ new(
+ "RabbitMqOptions:Password",
+ TestContainers.RabbitMqContainerConfiguration.Password),
+ new(
+ "RabbitMqOptions:Port",
+ RabbitMqTestContainer.GetMappedPublicPort(
+ TestContainers.RabbitMqContainerConfiguration.Port)
+ .ToString(NumberFormatInfo.InvariantInfo)),
+ new("MongoOptions:ConnectionString", MongoDbTestContainer.GetConnectionString()),
+ new("MongoOptions:DatabaseName", TestContainers.MongoContainerConfiguration.Name),
+ new(
+ "EventStoreOptions:ConnectionString",
+ EventStoreDbTestContainer.GetConnectionString())
+ });
}
private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider serviceProvider)
{
var httpContextAccessorMock = Substitute.For();
using var scope = serviceProvider.CreateScope();
- httpContextAccessorMock.HttpContext = new DefaultHttpContext { RequestServices = scope.ServiceProvider };
+
+ httpContextAccessorMock.HttpContext = new DefaultHttpContext
+ { RequestServices = scope.ServiceProvider };
httpContextAccessorMock.HttpContext.Request.Host = new HostString("localhost", 6012);
httpContextAccessorMock.HttpContext.Request.Scheme = "http";
@@ -305,8 +367,8 @@ private IHttpContextAccessor AddHttpContextAccessorMock(IServiceProvider service
}
public class TestWriteFixture : TestFixture
- where TEntryPoint : class
- where TWContext : DbContext
+where TEntryPoint : class
+where TWContext : DbContext
{
public Task ExecuteDbContextAsync(Func action)
{
@@ -320,7 +382,8 @@ public Task ExecuteDbContextAsync(Func action)
public Task ExecuteDbContextAsync(Func action)
{
- return ExecuteScopeAsync(sp => action(sp.GetService(), sp.GetService()));
+ return ExecuteScopeAsync(
+ sp => action(sp.GetService(), sp.GetService()));
}
public Task ExecuteDbContextAsync(Func> action)
@@ -335,94 +398,110 @@ public Task ExecuteDbContextAsync(Func> action)
public Task ExecuteDbContextAsync(Func> action)
{
- return ExecuteScopeAsync(sp => action(sp.GetService(), sp.GetService()));
+ return ExecuteScopeAsync(
+ sp => action(sp.GetService(), sp.GetService()));
}
- public Task InsertAsync(params T[] entities) where T : class
+ public Task InsertAsync(params T[] entities)
+ where T : class
{
- return ExecuteDbContextAsync(db =>
- {
- foreach (var entity in entities)
+ return ExecuteDbContextAsync(
+ db =>
{
- db.Set().Add(entity);
- }
+ foreach (var entity in entities)
+ {
+ db.Set().Add(entity);
+ }
- return db.SaveChangesAsync();
- });
+ return db.SaveChangesAsync();
+ });
}
- public async Task InsertAsync(TEntity entity) where TEntity : class
+ public async Task InsertAsync(TEntity entity)
+ where TEntity : class
{
- await ExecuteDbContextAsync(db =>
- {
- db.Set().Add(entity);
+ await ExecuteDbContextAsync(
+ db =>
+ {
+ db.Set().Add(entity);
- return db.SaveChangesAsync();
- });
+ return db.SaveChangesAsync();
+ });
}
public Task InsertAsync(TEntity entity, TEntity2 entity2)
- where TEntity : class
- where TEntity2 : class
+ where TEntity : class
+ where TEntity2 : class
{
- return ExecuteDbContextAsync(db =>
- {
- db.Set().Add(entity);
- db.Set().Add(entity2);
+ return ExecuteDbContextAsync(
+ db =>
+ {
+ db.Set().Add(entity);
+ db.Set().Add(entity2);
- return db.SaveChangesAsync();
- });
+ return db.SaveChangesAsync();
+ });
}
- public Task InsertAsync(TEntity entity, TEntity2 entity2, TEntity3 entity3)
- where TEntity : class
- where TEntity2 : class
- where TEntity3 : class
+ public Task InsertAsync(
+ TEntity entity,
+ TEntity2 entity2,
+ TEntity3 entity3
+ )
+ where TEntity : class
+ where TEntity2 : class
+ where TEntity3 : class
{
- return ExecuteDbContextAsync(db =>
- {
- db.Set().Add(entity);
- db.Set().Add(entity2);
- db.Set().Add(entity3);
+ return ExecuteDbContextAsync(
+ db =>
+ {
+ db.Set().Add(entity);
+ db.Set().Add(entity2);
+ db.Set().Add(entity3);
- return db.SaveChangesAsync();
- });
+ return db.SaveChangesAsync();
+ });
}
- public Task InsertAsync(TEntity entity, TEntity2 entity2, TEntity3 entity3,
- TEntity4 entity4)
- where TEntity : class
- where TEntity2 : class
- where TEntity3 : class
- where TEntity4 : class
+ public Task InsertAsync(
+ TEntity entity,
+ TEntity2 entity2,
+ TEntity3 entity3,
+ TEntity4 entity4
+ )
+ where TEntity : class
+ where TEntity2 : class
+ where TEntity3 : class
+ where TEntity4 : class
{
- return ExecuteDbContextAsync(db =>
- {
- db.Set().Add(entity);
- db.Set().Add(entity2);
- db.Set().Add(entity3);
- db.Set().Add(entity4);
+ return ExecuteDbContextAsync(
+ db =>
+ {
+ db.Set().Add(entity);
+ db.Set().Add(entity2);
+ db.Set().Add(entity3);
+ db.Set().Add(entity4);
- return db.SaveChangesAsync();
- });
+ return db.SaveChangesAsync();
+ });
}
public Task FindAsync(TKey id)
- where T : class, IEntity
+ where T : class, IEntity
{
return ExecuteDbContextAsync(db => db.Set().FindAsync(id).AsTask());
}
public Task FirstOrDefaultAsync()
- where T : class, IEntity
+ where T : class, IEntity
{
return ExecuteDbContextAsync(db => db.Set().FirstOrDefaultAsync());
}
}
public class TestReadFixture : TestFixture
- where TEntryPoint : class
- where TRContext : MongoDbContext
+where TEntryPoint : class
+where TRContext : MongoDbContext
{
public Task ExecuteReadContextAsync(Func action)
{
@@ -434,19 +513,22 @@ public Task ExecuteReadContextAsync(Func> action)
return ExecuteScopeAsync(sp => action(sp.GetRequiredService()));
}
- public async Task InsertMongoDbContextAsync(string collectionName, params T[] entities) where T : class
+ public async Task InsertMongoDbContextAsync(string collectionName, params T[] entities)
+ where T : class
{
- await ExecuteReadContextAsync(async db =>
- {
- await db.GetCollection(collectionName).InsertManyAsync(entities.ToList());
- });
+ await ExecuteReadContextAsync(
+ async db =>
+ {
+ await db.GetCollection(collectionName).InsertManyAsync(entities.ToList());
+ });
}
}
-public class TestFixture : TestWriteFixture
- where TEntryPoint : class
- where TWContext : DbContext
- where TRContext : MongoDbContext
+public class TestFixture
+ : TestWriteFixture
+where TEntryPoint : class
+where TWContext : DbContext
+where TRContext : MongoDbContext
{
public Task ExecuteReadContextAsync(Func action)
{
@@ -458,17 +540,19 @@ public Task ExecuteReadContextAsync(Func> action)
return ExecuteScopeAsync(sp => action(sp.GetRequiredService()));
}
- public async Task InsertMongoDbContextAsync(string collectionName, params T[] entities) where T : class
+ public async Task InsertMongoDbContextAsync(string collectionName, params T[] entities)
+ where T : class
{
- await ExecuteReadContextAsync(async db =>
- {
- await db.GetCollection(collectionName).InsertManyAsync(entities.ToList());
- });
+ await ExecuteReadContextAsync(
+ async db =>
+ {
+ await db.GetCollection(collectionName).InsertManyAsync(entities.ToList());
+ });
}
}
public class TestFixtureCore : IAsyncLifetime
- where TEntryPoint : class
+where TEntryPoint : class
{
private Respawner _reSpawnerDefaultDb;
private Respawner _reSpawnerPersistDb;
@@ -476,7 +560,10 @@ public class TestFixtureCore : IAsyncLifetime
private NpgsqlConnection PersistDbConnection { get; set; }
- public TestFixtureCore(TestFixture integrationTestFixture, ITestOutputHelper outputHelper)
+ public TestFixtureCore(
+ TestFixture integrationTestFixture,
+ ITestOutputHelper outputHelper
+ )
{
Fixture = integrationTestFixture;
integrationTestFixture.RegisterServices(RegisterTestsServices);
@@ -505,13 +592,15 @@ private async Task InitPostgresAsync()
if (!string.IsNullOrEmpty(persistOptions?.ConnectionString))
{
- await Fixture.PersistMessageBackgroundService.StartAsync(Fixture.CancellationTokenSource.Token);
+ await Fixture.PersistMessageBackgroundService.StartAsync(
+ Fixture.CancellationTokenSource.Token);
PersistDbConnection = new NpgsqlConnection(persistOptions.ConnectionString);
await PersistDbConnection.OpenAsync();
- _reSpawnerPersistDb = await Respawner.CreateAsync(PersistDbConnection,
- new RespawnerOptions { DbAdapter = DbAdapter.Postgres });
+ _reSpawnerPersistDb = await Respawner.CreateAsync(
+ PersistDbConnection,
+ new RespawnerOptions { DbAdapter = DbAdapter.Postgres });
}
if (!string.IsNullOrEmpty(postgresOptions?.ConnectionString))
@@ -519,8 +608,9 @@ private async Task InitPostgresAsync()
DefaultDbConnection = new NpgsqlConnection(postgresOptions.ConnectionString);
await DefaultDbConnection.OpenAsync();
- _reSpawnerDefaultDb = await Respawner.CreateAsync(DefaultDbConnection,
- new RespawnerOptions { DbAdapter = DbAdapter.Postgres });
+ _reSpawnerDefaultDb = await Respawner.CreateAsync(
+ DefaultDbConnection,
+ new RespawnerOptions { DbAdapter = DbAdapter.Postgres });
await SeedDataAsync();
}
@@ -532,7 +622,8 @@ private async Task ResetPostgresAsync()
{
await _reSpawnerPersistDb.ResetAsync(PersistDbConnection);
- await Fixture.PersistMessageBackgroundService.StopAsync(Fixture.CancellationTokenSource.Token);
+ await Fixture.PersistMessageBackgroundService.StopAsync(
+ Fixture.CancellationTokenSource.Token);
}
if (DefaultDbConnection is not null)
@@ -545,8 +636,10 @@ private async Task ResetMongoAsync(CancellationToken cancellationToken = default
{
//https://stackoverflow.com/questions/3366397/delete-everything-in-a-mongodb-database
var dbClient = new MongoClient(Fixture.MongoDbTestContainer?.GetConnectionString());
- var collections = await dbClient.GetDatabase(TestContainers.MongoContainerConfiguration.Name)
- .ListCollectionsAsync(cancellationToken: cancellationToken);
+
+ var collections = await dbClient
+ .GetDatabase(TestContainers.MongoContainerConfiguration.Name)
+ .ListCollectionsAsync(cancellationToken: cancellationToken);
foreach (var collection in collections.ToList())
{
@@ -557,27 +650,30 @@ await dbClient.GetDatabase(TestContainers.MongoContainerConfiguration.Name)
private async Task ResetRabbitMqAsync(CancellationToken cancellationToken = default)
{
- var port = Fixture.RabbitMqTestContainer?.GetMappedPublicPort(TestContainers.RabbitMqContainerConfiguration
- .ApiPort)
- ?? TestContainers.RabbitMqContainerConfiguration.ApiPort;
+ var port = Fixture.RabbitMqTestContainer?.GetMappedPublicPort(
+ TestContainers.RabbitMqContainerConfiguration
+ .ApiPort) ??
+ TestContainers.RabbitMqContainerConfiguration.ApiPort;
var managementClient = new ManagementClient(Fixture.RabbitMqTestContainer?.Hostname,
TestContainers.RabbitMqContainerConfiguration?.UserName,
TestContainers.RabbitMqContainerConfiguration?.Password, port);
var bd = await managementClient.GetBindingsAsync(cancellationToken);
- var bindings = bd.Where(x => !string.IsNullOrEmpty(x.Source) && !string.IsNullOrEmpty(x.Destination));
+
+ var bindings = bd.Where(
+ x => !string.IsNullOrEmpty(x.Source) && !string.IsNullOrEmpty(x.Destination));
foreach (var binding in bindings)
{
await managementClient.DeleteBindingAsync(binding, cancellationToken);
}
- var queues = await managementClient.GetQueuesAsync(cancellationToken);
+ var queues = await managementClient.GetQueuesAsync(cancellationToken: cancellationToken);
foreach (var queue in queues)
{
- await managementClient.DeleteQueueAsync(queue, cancellationToken);
+ await managementClient.PurgeAsync(queue, cancellationToken);
}
}
@@ -590,6 +686,7 @@ private async Task SeedDataAsync()
using var scope = Fixture.ServiceProvider.CreateScope();
var seeders = scope.ServiceProvider.GetServices();
+
foreach (var seeder in seeders)
{
await seeder.SeedAllAsync();
@@ -598,13 +695,14 @@ private async Task SeedDataAsync()
}
public abstract class TestReadBase : TestFixtureCore
- //,IClassFixture>
- where TEntryPoint : class
- where TRContext : MongoDbContext
+// ,IClassFixture>
+where TEntryPoint : class
+where TRContext : MongoDbContext
{
protected TestReadBase(
- TestReadFixture integrationTestFixture, ITestOutputHelper outputHelper = null) : base(
- integrationTestFixture, outputHelper)
+ TestReadFixture integrationTestFixture,
+ ITestOutputHelper outputHelper = null
+ ) : base(integrationTestFixture, outputHelper)
{
Fixture = integrationTestFixture;
}
@@ -613,13 +711,14 @@ protected TestReadBase(
}
public abstract class TestWriteBase : TestFixtureCore
- //,IClassFixture>
- where TEntryPoint : class
- where TWContext : DbContext
+//,IClassFixture>
+where TEntryPoint : class
+where TWContext : DbContext
{
protected TestWriteBase(
- TestWriteFixture integrationTestFixture, ITestOutputHelper outputHelper = null) : base(
- integrationTestFixture, outputHelper)
+ TestWriteFixture integrationTestFixture,
+ ITestOutputHelper outputHelper = null
+ ) : base(integrationTestFixture, outputHelper)
{
Fixture = integrationTestFixture;
}
@@ -628,13 +727,15 @@ protected TestWriteBase(
}
public abstract class TestBase : TestFixtureCore
- //,IClassFixture>
- where TEntryPoint : class
- where TWContext : DbContext
- where TRContext : MongoDbContext
+//,IClassFixture>
+where TEntryPoint : class
+where TWContext : DbContext
+where TRContext : MongoDbContext
{
protected TestBase(
- TestFixture integrationTestFixture, ITestOutputHelper outputHelper = null) :
+ TestFixture integrationTestFixture,
+ ITestOutputHelper outputHelper = null
+ ) :
base(integrationTestFixture, outputHelper)
{
Fixture = integrationTestFixture;
diff --git a/src/BuildingBlocks/Web/SlugifyParameterTransformer.cs b/src/BuildingBlocks/Web/SlugifyParameterTransformer.cs
index 9aecf771..29bc834a 100644
--- a/src/BuildingBlocks/Web/SlugifyParameterTransformer.cs
+++ b/src/BuildingBlocks/Web/SlugifyParameterTransformer.cs
@@ -1,3 +1,4 @@
+using System.Globalization;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Routing;
@@ -10,6 +11,6 @@ public string TransformOutbound(object value)
// Slugify value
return value == null
? null
- : Regex.Replace(value.ToString() ?? string.Empty, "([a-z])([A-Z])", "$1-$2").ToLower();
+ : Regex.Replace(value.ToString() ?? string.Empty, "([a-z])([A-Z])", "$1-$2").ToLower(CultureInfo.CurrentCulture);
}
}
diff --git a/src/Services/Booking/src/Booking/Booking/Models/Booking.cs b/src/Services/Booking/src/Booking/Booking/Models/Booking.cs
index a895426f..354f7431 100644
--- a/src/Services/Booking/src/Booking/Booking/Models/Booking.cs
+++ b/src/Services/Booking/src/Booking/Booking/Models/Booking.cs
@@ -32,10 +32,10 @@ public override void When(object @event)
switch (@event)
{
case BookingCreatedDomainEvent bookingCreated:
- {
- Apply(bookingCreated);
- return;
- }
+ {
+ Apply(bookingCreated);
+ return;
+ }
}
}
diff --git a/src/Services/Flight/src/Flight/Data/Seed/InitialData.cs b/src/Services/Flight/src/Flight/Data/Seed/InitialData.cs
index 70b5494f..695251ee 100644
--- a/src/Services/Flight/src/Flight/Data/Seed/InitialData.cs
+++ b/src/Services/Flight/src/Flight/Data/Seed/InitialData.cs
@@ -45,7 +45,7 @@ static InitialData()
ArriveDate.Of(new DateTime(2022, 1, 31, 14, 0, 0)),
AirportId.Of(Airports.Last().Id), DurationMinutes.Of(120m),
FlightDate.Of(new DateTime(2022, 1, 31, 13, 0, 0)), global::Flight.Flights.Enums.FlightStatus.Completed,
- Price.Of((decimal)8000))
+ Price.Of(8000))
};
Seats = new List
diff --git a/src/Services/Flight/tests/EndToEndTest/Flight/Features/GetFlightByIdTests.cs b/src/Services/Flight/tests/EndToEndTest/Flight/Features/GetFlightByIdTests.cs
index 232d7387..057e03a0 100644
--- a/src/Services/Flight/tests/EndToEndTest/Flight/Features/GetFlightByIdTests.cs
+++ b/src/Services/Flight/tests/EndToEndTest/Flight/Features/GetFlightByIdTests.cs
@@ -25,7 +25,7 @@ public async Task should_retrive_a_flight_by_id_currectly()
await Fixture.SendAsync(command);
// Act
- var route = ApiRoutes.Flight.GetFlightById.Replace(ApiRoutes.Flight.Id, command.Id.ToString());
+ var route = ApiRoutes.Flight.GetFlightById.Replace(ApiRoutes.Flight.Id, command.Id.ToString(), StringComparison.CurrentCulture);
var result = await Fixture.HttpClient.GetAsync(route);
// Assert
diff --git a/src/Services/Flight/tests/UnitTest/Common/DbContextFactory.cs b/src/Services/Flight/tests/UnitTest/Common/DbContextFactory.cs
index 69abdb82..b3d30c7e 100644
--- a/src/Services/Flight/tests/UnitTest/Common/DbContextFactory.cs
+++ b/src/Services/Flight/tests/UnitTest/Common/DbContextFactory.cs
@@ -65,7 +65,7 @@ private static void FlightDataSeeder(FlightDbContext context)
ArriveDate.Of( new DateTime(2022, 1, 31, 14, 0, 0)),
AirportId.Of( _airportId2), DurationMinutes.Of(120m),
FlightDate.Of( new DateTime(2022, 1, 31)), FlightStatus.Completed,
- Price.Of((decimal)8000))
+ Price.Of(8000))
};
context.Flights.AddRange(flights);