diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1330824 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,402 @@ +root = true + +[*] +indent_style = space +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.cs] +#### Стили именования #### + +# Правила именования + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = error +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = error +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = error +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Спецификации символов + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Стили именования + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case +csharp_style_throw_expression = true:warning +csharp_style_prefer_null_check_over_type_check = true:suggestion +csharp_prefer_simple_default_expression = true:warning +csharp_style_prefer_local_over_anonymous_function = true:warning +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_implicit_object_creation_when_type_is_apparent = true:warning +csharp_style_prefer_tuple_swap = true:suggestion +csharp_style_prefer_utf8_string_literals = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_space_around_binary_operators = before_and_after +csharp_indent_labels = one_less_than_current +csharp_style_deconstructed_variable_declaration = true:warning +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent +csharp_style_conditional_delegate_call = true:warning +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_not_pattern = true:suggestion +csharp_style_prefer_extended_property_pattern = true:suggestion +csharp_style_var_for_built_in_types = false:warning +csharp_style_var_when_type_is_apparent = false:warning +csharp_style_var_elsewhere = false:warning +csharp_prefer_simple_using_statement = true:warning +csharp_prefer_braces = true:warning +csharp_style_namespace_declarations = file_scoped:warning +csharp_style_prefer_method_group_conversion = true:warning +csharp_style_prefer_top_level_statements = true:warning +csharp_style_prefer_primary_constructors = false:error +csharp_using_directive_placement = outside_namespace:warning +csharp_style_allow_embedded_statements_on_same_line_experimental = false:warning +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:warning +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:warning +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:warning +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:warning +csharp_prefer_static_local_function = true:warning +csharp_style_prefer_readonly_struct = true:warning +csharp_style_prefer_readonly_struct_member = true:warning +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:warning +csharp_style_expression_bodied_indexers = true:warning +csharp_style_expression_bodied_accessors = true:warning +csharp_style_expression_bodied_lambdas = true:warning +csharp_style_expression_bodied_local_functions = true:warning +dotnet_diagnostic.CA1200.severity = warning +dotnet_diagnostic.SYSLIB1045.severity = warning +dotnet_diagnostic.CA1309.severity = warning +dotnet_diagnostic.CA1311.severity = warning +dotnet_diagnostic.SYSLIB1054.severity = error +dotnet_diagnostic.CA1507.severity = warning +dotnet_diagnostic.CA1805.severity = warning +dotnet_diagnostic.CA1824.severity = warning +dotnet_diagnostic.CA1825.severity = warning +dotnet_diagnostic.CA1841.severity = warning +dotnet_diagnostic.CA1845.severity = warning +dotnet_diagnostic.CA1855.severity = warning +dotnet_diagnostic.CA2016.severity = warning +dotnet_diagnostic.CA2020.severity = warning +dotnet_diagnostic.CA2244.severity = warning +dotnet_diagnostic.CA2246.severity = warning + +[*.vb] +#### Стили именования #### + +# Правила именования + +dotnet_naming_rule.interface_should_be_начинается_с_i.severity = suggestion +dotnet_naming_rule.interface_should_be_начинается_с_i.symbols = interface +dotnet_naming_rule.interface_should_be_начинается_с_i.style = начинается_с_i + +dotnet_naming_rule.типы_should_be_всечастиспрописнойбуквы.severity = suggestion +dotnet_naming_rule.типы_should_be_всечастиспрописнойбуквы.symbols = типы +dotnet_naming_rule.типы_should_be_всечастиспрописнойбуквы.style = всечастиспрописнойбуквы + +dotnet_naming_rule.не_являющиеся_полем_члены_should_be_всечастиспрописнойбуквы.severity = suggestion +dotnet_naming_rule.не_являющиеся_полем_члены_should_be_всечастиспрописнойбуквы.symbols = не_являющиеся_полем_члены +dotnet_naming_rule.не_являющиеся_полем_члены_should_be_всечастиспрописнойбуквы.style = всечастиспрописнойбуквы + +# Спецификации символов + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.типы.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.типы.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected +dotnet_naming_symbols.типы.required_modifiers = + +dotnet_naming_symbols.не_являющиеся_полем_члены.applicable_kinds = property, event, method +dotnet_naming_symbols.не_являющиеся_полем_члены.applicable_accessibilities = public, friend, private, protected, protected_friend, private_protected +dotnet_naming_symbols.не_являющиеся_полем_члены.required_modifiers = + +# Стили именования + +dotnet_naming_style.начинается_с_i.required_prefix = I +dotnet_naming_style.начинается_с_i.required_suffix = +dotnet_naming_style.начинается_с_i.word_separator = +dotnet_naming_style.начинается_с_i.capitalization = pascal_case + +dotnet_naming_style.всечастиспрописнойбуквы.required_prefix = +dotnet_naming_style.всечастиспрописнойбуквы.required_suffix = +dotnet_naming_style.всечастиспрописнойбуквы.word_separator = +dotnet_naming_style.всечастиспрописнойбуквы.capitalization = pascal_case + +dotnet_naming_style.всечастиспрописнойбуквы.required_prefix = +dotnet_naming_style.всечастиспрописнойбуквы.required_suffix = +dotnet_naming_style.всечастиспрописнойбуквы.word_separator = +dotnet_naming_style.всечастиспрописнойбуквы.capitalization = pascal_case + +[*.{cs,vb}] +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = true +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_auto_properties = true:warning +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +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_compound_assignment = true:warning +dotnet_style_prefer_simplified_interpolation = true:warning +dotnet_style_namespace_match_folder = true:error +dotnet_style_operator_placement_when_wrapping = beginning_of_line +tab_width = 4 +indent_size = 4 +insert_final_newline = true +dotnet_code_quality_unused_parameters = all:warning +dotnet_style_predefined_type_for_locals_parameters_members = true:error +dotnet_style_predefined_type_for_member_access = true:error +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning +dotnet_style_allow_multiple_blank_lines_experimental = false:warning +dotnet_style_allow_statement_immediately_after_block_experimental = false:warning +dotnet_style_readonly_field = true:warning +dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:warning +dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning +dotnet_diagnostic.CA1050.severity = error +dotnet_diagnostic.CA1010.severity = warning +dotnet_diagnostic.CA1018.severity = warning +dotnet_diagnostic.CA1041.severity = warning +dotnet_diagnostic.CA1061.severity = warning +dotnet_diagnostic.CA1068.severity = warning +dotnet_diagnostic.CA1069.severity = warning +dotnet_diagnostic.CA1304.severity = warning +dotnet_diagnostic.CA1305.severity = warning +dotnet_diagnostic.CA1310.severity = warning +dotnet_diagnostic.CA2101.severity = warning +dotnet_diagnostic.CA1401.severity = warning +dotnet_diagnostic.CA1707.severity = warning +dotnet_diagnostic.CA1708.severity = warning +dotnet_diagnostic.CA1710.severity = warning +dotnet_diagnostic.CA1711.severity = warning +dotnet_diagnostic.CA1712.severity = warning +dotnet_diagnostic.CA1715.severity = warning +dotnet_diagnostic.CA1716.severity = warning +dotnet_diagnostic.CA1720.severity = warning +dotnet_diagnostic.CA1725.severity = warning +dotnet_diagnostic.CA1727.severity = warning +dotnet_diagnostic.CA1826.severity = warning +dotnet_diagnostic.CA1827.severity = warning +dotnet_diagnostic.CA1828.severity = warning +dotnet_diagnostic.CA1829.severity = warning +dotnet_diagnostic.CA1830.severity = warning +dotnet_diagnostic.CA1832.severity = warning +dotnet_diagnostic.CA1833.severity = warning +dotnet_diagnostic.CA1834.severity = warning +dotnet_diagnostic.CA1835.severity = warning +dotnet_diagnostic.CA1836.severity = warning +dotnet_diagnostic.CA1837.severity = warning +dotnet_diagnostic.CA1839.severity = warning +dotnet_diagnostic.CA1840.severity = warning +dotnet_diagnostic.CA1842.severity = warning +dotnet_diagnostic.CA1843.severity = warning +dotnet_diagnostic.CA1846.severity = warning +dotnet_diagnostic.CA1847.severity = warning +dotnet_diagnostic.CA1848.severity = silent +dotnet_diagnostic.CA1850.severity = warning +dotnet_diagnostic.CA1852.severity = suggestion +dotnet_diagnostic.CA1853.severity = warning +dotnet_diagnostic.CA1854.severity = warning +dotnet_diagnostic.CA2009.severity = warning +dotnet_diagnostic.CA2011.severity = warning +dotnet_diagnostic.CA2012.severity = error +dotnet_diagnostic.CA2019.severity = warning +dotnet_diagnostic.CA3061.severity = warning +dotnet_diagnostic.CA3075.severity = warning +dotnet_diagnostic.CA3076.severity = warning +dotnet_diagnostic.CA3077.severity = warning +dotnet_diagnostic.CA3147.severity = warning +dotnet_diagnostic.CA5350.severity = warning +dotnet_diagnostic.CA5351.severity = warning +dotnet_diagnostic.CA5359.severity = warning +dotnet_diagnostic.CA5360.severity = warning +dotnet_diagnostic.CA5363.severity = warning +dotnet_diagnostic.CA5364.severity = warning +dotnet_diagnostic.CA5365.severity = warning +dotnet_diagnostic.CA5366.severity = warning +dotnet_diagnostic.CA5379.severity = warning +dotnet_diagnostic.CA5384.severity = warning +dotnet_diagnostic.CA5385.severity = warning +dotnet_diagnostic.CA5397.severity = warning +dotnet_diagnostic.CA1816.severity = warning +dotnet_diagnostic.CA2201.severity = warning +dotnet_diagnostic.CA2208.severity = warning +dotnet_diagnostic.CA2211.severity = warning +dotnet_diagnostic.CA2215.severity = warning +dotnet_diagnostic.CA2219.severity = warning +dotnet_diagnostic.CA2229.severity = warning +dotnet_diagnostic.CA2231.severity = warning +dotnet_diagnostic.CA2241.severity = warning +dotnet_diagnostic.CA2242.severity = error +dotnet_diagnostic.CA2245.severity = warning +dotnet_diagnostic.CA2248.severity = warning +dotnet_diagnostic.CA2249.severity = warning +dotnet_diagnostic.CA2250.severity = warning +dotnet_diagnostic.CA2253.severity = warning +dotnet_diagnostic.CA2254.severity = warning +dotnet_diagnostic.CA1047.severity = warning +dotnet_diagnostic.CA1802.severity = warning +dotnet_diagnostic.CA1810.severity = warning +dotnet_diagnostic.CA1821.severity = error +dotnet_diagnostic.CA1823.severity = warning +dotnet_diagnostic.CA2013.severity = warning +dotnet_diagnostic.CA2014.severity = error +dotnet_diagnostic.CA2200.severity = warning + +# Newline settings +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true + +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = error +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_rule.static_fields_should_have_prefix.severity = error +dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields +dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style + +dotnet_naming_symbols.static_fields.applicable_kinds = field +dotnet_naming_symbols.static_fields.required_modifiers = static +dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected + +dotnet_naming_style.static_prefix_style.required_prefix = s_ +dotnet_naming_style.static_prefix_style.capitalization = camel_case + +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = error +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 + +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning + +dotnet_diagnostic.IDE0005.severity = warning +dotnet_diagnostic.IDE0035.severity = warning +dotnet_diagnostic.IDE0036.severity = warning +dotnet_diagnostic.IDE0043.severity = warning +dotnet_diagnostic.IDE0044.severity = suggestion +dotnet_diagnostic.IDE0055.severity = warning +dotnet_diagnostic.IDE0161.severity = warning +dotnet_diagnostic.IDE0290.severity = error + +dotnet_diagnostic.HAA0101.severity = suggestion +dotnet_diagnostic.HAA0301.severity = suggestion +dotnet_diagnostic.HAA0303.severity = suggestion +dotnet_diagnostic.HAA0401.severity = suggestion +dotnet_diagnostic.HAA0601.severity = suggestion + +dotnet_diagnostic.CS8597.severity = error +dotnet_diagnostic.CS8600.severity = error +dotnet_diagnostic.CS8601.severity = error +dotnet_diagnostic.CS8602.severity = error +dotnet_diagnostic.CS8603.severity = error +dotnet_diagnostic.CS8604.severity = error +dotnet_diagnostic.CS8605.severity = error +dotnet_diagnostic.CS8607.severity = error +dotnet_diagnostic.CS8608.severity = error +dotnet_diagnostic.CS8609.severity = error +dotnet_diagnostic.CS8610.severity = error +dotnet_diagnostic.CS8611.severity = error +dotnet_diagnostic.CS8612.severity = error +dotnet_diagnostic.CS8613.severity = error +dotnet_diagnostic.CS8614.severity = error +dotnet_diagnostic.CS8615.severity = error +dotnet_diagnostic.CS8616.severity = error +dotnet_diagnostic.CS8617.severity = error +dotnet_diagnostic.CS8618.severity = error +dotnet_diagnostic.CS8619.severity = error +dotnet_diagnostic.CS8620.severity = error +dotnet_diagnostic.CS8621.severity = error +dotnet_diagnostic.CS8622.severity = error +dotnet_diagnostic.CS8624.severity = error +dotnet_diagnostic.CS8625.severity = error +dotnet_diagnostic.CS8629.severity = error +dotnet_diagnostic.CS8631.severity = error +dotnet_diagnostic.CS8633.severity = error +dotnet_diagnostic.CS8634.severity = error +dotnet_diagnostic.CS8643.severity = error +dotnet_diagnostic.CS8644.severity = error +dotnet_diagnostic.CS8645.severity = error +dotnet_diagnostic.CS8655.severity = error +dotnet_diagnostic.CS8667.severity = error +dotnet_diagnostic.CS8670.severity = error +dotnet_diagnostic.CS8714.severity = error +dotnet_diagnostic.CS8762.severity = error +dotnet_diagnostic.CS8763.severity = error +dotnet_diagnostic.CS8764.severity = error +dotnet_diagnostic.CS8765.severity = error +dotnet_diagnostic.CS8766.severity = error +dotnet_diagnostic.CS8767.severity = error +dotnet_diagnostic.CS8768.severity = error +dotnet_diagnostic.CS8769.severity = error +dotnet_diagnostic.CS8770.severity = error +dotnet_diagnostic.CS8774.severity = error +dotnet_diagnostic.CS8776.severity = error +dotnet_diagnostic.CS8775.severity = error +dotnet_diagnostic.CS8777.severity = error +dotnet_diagnostic.CS8819.severity = error +dotnet_diagnostic.CS8824.severity = error +dotnet_diagnostic.CS8825.severity = error +dotnet_diagnostic.CS8847.severity = error diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0b6d615 --- /dev/null +++ b/.gitignore @@ -0,0 +1,597 @@ +.idea/ +build/ + + +# Created by https://www.gitignore.io/api/csharp,jetbrains,visualstudio +# Edit at https://www.gitignore.io/?templates=csharp,jetbrains,visualstudio + +### Csharp ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +### JetBrains ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### JetBrains Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint + +### VisualStudio ### + +# User-specific files + +# User-specific files (MonoDevelop/Xamarin Studio) + +# Mono auto generated files + +# Build results + +# Visual Studio 2015/2017 cache/options directory +# Uncomment if you have tasks that create the project's static files in wwwroot + +# Visual Studio 2017 auto generated files + +# MSTest test Results + +# NUnit + +# Build Results of an ATL Project + +# Benchmark Results + +# .NET Core + +# StyleCop + +# Files built by Visual Studio + +# Chutzpah Test files + +# Visual C++ cache files + +# Visual Studio profiler + +# Visual Studio Trace Files + +# TFS 2012 Local Workspace + +# Guidance Automation Toolkit + +# ReSharper is a .NET coding add-in + +# JustCode is a .NET coding add-in + +# TeamCity is a build add-in + +# DotCover is a Code Coverage Tool + +# AxoCover is a Code Coverage Tool + +# Visual Studio code coverage results + +# NCrunch + +# MightyMoose + +# Web workbench (sass) + +# Installshield output folder + +# DocProject is a documentation generator add-in + +# Click-Once directory + +# Publish Web Output +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted + +# NuGet Packages +# NuGet Symbol Packages +# The packages folder can be ignored because of Package Restore +# except build/, which is used as an MSBuild target. +# Uncomment if necessary however generally it will be regenerated when needed +# NuGet v3's project.json files produces more ignorable files + +# Microsoft Azure Build Output + +# Microsoft Azure Emulator + +# Windows Store app package directories and files + +# Visual Studio cache files +# files ending in .cache can be ignored +# but keep track of directories ending in .cache + +# Others + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) + +# RIA/Silverlight projects + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) + +# SQL Server files + +# Business Intelligence projects + +# Microsoft Fakes + +# GhostDoc plugin setting file + +# Node.js Tools for Visual Studio + +# Visual Studio 6 build log + +# Visual Studio 6 workspace options file + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) + +# Visual Studio LightSwitch build output + +# Paket dependency manager + +# FAKE - F# Make + +# CodeRush personal settings + +# Python Tools for Visual Studio (PTVS) + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio + +# Telerik's JustMock configuration file + +# BizTalk build output + +# OpenCover UI analysis results + +# Azure Stream Analytics local run output + +# MSBuild Binary and Structured Log + +# NVidia Nsight GPU debugger configuration file + +# MFractors (Xamarin productivity tool) working folder + +# Local History for Visual Studio + +# BeatPulse healthcheck temp database + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 + +# End of https://www.gitignore.io/api/csharp,jetbrains,visualstudio +/examples/StreetlightsAPI/Properties/launchSettings.json diff --git a/README.md b/README.md index 4e37a21..6344251 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,52 @@ # SourceGenLinq -Simple implementation of flexible parameterized sorting for IQuariable using IncrementalGenerator + +Simple implementation of flexible parameterized sorting for IQuariable using IncrementalGenerator. + +## Usage + +> Tested on net8 + +0. Install library: + +```xml + + + + +``` + +1. Define DTO class: + +```csharp +public class Tester +{ + public Guid Id { get; set; } + + public required string Name { get; set; } + public required string Comment { get; set; } + public required double Test { get; set; } + + public QazWsx? QazWsx { get; set; } +} + +public class QazWsx; +``` + +2. Define sorter with generic attribute `SortQuariable`: + +```csharp +[SortQuariable] +public static partial class MyTesterSorter; +``` + +3. Use: + +```csharp +IQueryable testers = default!; + +testers = testers.Sort(new() +{ + { TesterSort.TesterProperty.IdProperty, SortMode.Asc }, + { TesterSort.TesterProperty.CommentProperty, SortMode.Desc }, +}); +``` diff --git a/Sample/Program.cs b/Sample/Program.cs new file mode 100644 index 0000000..2b0299b --- /dev/null +++ b/Sample/Program.cs @@ -0,0 +1,59 @@ +using SourceGenLinq.Abstractions; + +using TesterSample; + +Console.WriteLine("Hello, World!"); + +IQueryable testers = new Tester[] +{ + new() + { + Id = Guid.NewGuid(), + Name = "Test", + Comment = "Test", + Test = 22, + }, + new() + { + Id = Guid.NewGuid(), + Name = "Test 2", + Comment = "Test 3", + Test = 100, + }, +}.AsQueryable(); + +IQueryable orderedTesters = testers.Sort(new() +{ + { TesterSort.TesterProperty.IdProperty, SortMode.Asc }, + { TesterSort.TesterProperty.CommentProperty, SortMode.Desc }, +}); + +Console.WriteLine(); + +namespace TesterSample +{ + [SortQuariable] + public static partial class TesterSort2; + + public class Tester + { + public Guid Id { get; set; } + + public required string Name { get; set; } + public required string Comment { get; set; } + public required double Test { get; set; } + + public QazWsx? QazWsx { get; set; } + } + + [SortQuariable] + public static partial class QazWsxSorter; + + public class QazWsx + { + public Guid Id { get; set; } + public Guid Говно { get; set; } + + public required string Name { get; set; } + } +} diff --git a/Sample/Sample.csproj b/Sample/Sample.csproj new file mode 100644 index 0000000..589cfb8 --- /dev/null +++ b/Sample/Sample.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/SourceGenLinq.Abstractions/SortMode.cs b/SourceGenLinq.Abstractions/SortMode.cs new file mode 100644 index 0000000..897f01d --- /dev/null +++ b/SourceGenLinq.Abstractions/SortMode.cs @@ -0,0 +1,7 @@ +namespace SourceGenLinq.Abstractions; + +public enum SortMode +{ + Asc, + Desc, +} diff --git a/SourceGenLinq.Abstractions/SortQuariableAttribute.cs b/SourceGenLinq.Abstractions/SortQuariableAttribute.cs new file mode 100644 index 0000000..b9ac474 --- /dev/null +++ b/SourceGenLinq.Abstractions/SortQuariableAttribute.cs @@ -0,0 +1,4 @@ +namespace SourceGenLinq.Abstractions; + +[AttributeUsage(AttributeTargets.Class)] +public class SortQuariableAttribute : Attribute where T : class; diff --git a/SourceGenLinq.Abstractions/SourceGenLinq.Abstractions.csproj b/SourceGenLinq.Abstractions/SourceGenLinq.Abstractions.csproj new file mode 100644 index 0000000..aef9b2c --- /dev/null +++ b/SourceGenLinq.Abstractions/SourceGenLinq.Abstractions.csproj @@ -0,0 +1,26 @@ + + + + net6.0 + enable + enable + latest + 0.0.1 + SourceGenLinq.Abstractions + SourceGenLinq.Abstractions + README.md + Simple implementation of flexible parameterized sorting for IQuariable using IncrementalGenerator + Apache-2.0 + https://github.com/yurvon-screamo/SourceGenLinq + True + snupkg + + + + + True + \ + + + + diff --git a/SourceGenLinq.Abstractions/SourceGenLinq.Abstractions.sln b/SourceGenLinq.Abstractions/SourceGenLinq.Abstractions.sln new file mode 100644 index 0000000..d62e0c0 --- /dev/null +++ b/SourceGenLinq.Abstractions/SourceGenLinq.Abstractions.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SourceGenLinq.Abstractions", "SourceGenLinq.Abstractions.csproj", "{70FD2DB6-3039-4170-B474-6D9C959CA79F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {70FD2DB6-3039-4170-B474-6D9C959CA79F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {70FD2DB6-3039-4170-B474-6D9C959CA79F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {70FD2DB6-3039-4170-B474-6D9C959CA79F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {70FD2DB6-3039-4170-B474-6D9C959CA79F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {ED9260E0-3F67-4748-8AD0-224C89971EDA} + EndGlobalSection +EndGlobal diff --git a/SourceGenLinq.Generator/OrderByIncrementalGenerator.cs b/SourceGenLinq.Generator/OrderByIncrementalGenerator.cs new file mode 100644 index 0000000..3417b5e --- /dev/null +++ b/SourceGenLinq.Generator/OrderByIncrementalGenerator.cs @@ -0,0 +1,177 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +namespace SourceGenLinq.Generator; + +[Generator] +public class OrderByIncrementalGenerator : IIncrementalGenerator +{ + public void Initialize(IncrementalGeneratorInitializationContext context) + { + IncrementalValuesProvider valuesProvider = context.SyntaxProvider + .CreateSyntaxProvider( + predicate: (p, _) => IsSyntaxTargetForGeneration(p), + transform: (p, _) => GetSemanticTarget(p)) + .Where(t => t.DataType is not null); + + context.RegisterSourceOutput(valuesProvider, (c, p) => + { + if (p.DataType is null || p.NamespacePrefix is null) + { + return; + } + + string identity = p.DataType; + + string enumSource = string.Empty; + string orderSource = string.Empty; + + foreach (string propertyName in p.PropertyNames) + { + enumSource += $"\n {propertyName}Property,"; + + orderSource += $"\n {identity}Property.{propertyName}Property when item.Value is SourceGenLinq.Abstractions.SortMode.Asc => sources.OrderBy(t => t.{propertyName}),"; + orderSource += $"\n {identity}Property.{propertyName}Property when item.Value is SourceGenLinq.Abstractions.SortMode.Desc => sources.OrderByDescending(t => t.{propertyName}),"; + orderSource += '\n'; + } + + string source = @"using System; +using System.Collections.Generic; +using System.Linq; + +"; + + source += p.NamespacePrefix == string.Empty + ? string.Empty + : $"namespace {p.NamespacePrefix};\n\n"; + + source += $@"public static partial class {identity}Sort +{{ + public enum {identity}Property + {{{enumSource} + }} + + public sealed class {identity}SortInput : Dictionary<{identity}Property, SourceGenLinq.Abstractions.SortMode>; + + public static IQueryable<{identity}> Sort(this IQueryable<{identity}> sources, {identity}SortInput input) + {{ + foreach (KeyValuePair<{identity}Property, SourceGenLinq.Abstractions.SortMode> item in input) + {{ + sources = item.Key switch + {{{orderSource} + _ => throw new NotImplementedException(), + }}; + }} + + return sources; + }} +}} +"; + + string file; + + if (p.NamespacePrefix == string.Empty) + { + file = p.DataType; + } + else + { + file = p.NamespacePrefix + '.' + p.DataType; + } + + c.AddSource($"{file}.Generated.cs", source); + }); + } + + static bool IsSyntaxTargetForGeneration(SyntaxNode node) + { + return node is ClassDeclarationSyntax classDeclaration && + classDeclaration.AttributeLists.Any(); + } + + static Target GetSemanticTarget(GeneratorSyntaxContext context) + { + if (context.Node is ClassDeclarationSyntax classDeclaration) + { + foreach (AttributeListSyntax listSyntax in classDeclaration.AttributeLists) + { + foreach (AttributeSyntax attribute in listSyntax.Attributes) + { + TypeInfo typeInfo = context.SemanticModel.GetTypeInfo(attribute); + + if (typeInfo.Type?.Name == "SortQuariableAttribute") + { + IEnumerable childNodes = attribute + .ChildNodes() + .OfType(); + + foreach (GenericNameSyntax node in childNodes) + { + TypeArgumentListSyntax argumentListSyntax = node.TypeArgumentList; + + foreach (TypeSyntax typeSyntax in argumentListSyntax.Arguments) + { + ITypeSymbol? typeSymbol = context + .SemanticModel + .GetTypeInfo(typeSyntax) + .Type; + + if (typeSymbol is null) + { + continue; + } + + INamespaceSymbol namespaceSymbol = typeSymbol.ContainingNamespace; + + IEnumerable propertySymbols = typeSymbol + .GetMembers() + .OfType(); + + List propertyNames = new(); + + foreach (IPropertySymbol property in propertySymbols) + { + if (property.IsStatic || property.IsWriteOnly) + { + continue; + } + + ITypeSymbol propertyType = property.Type; + + if (propertyType.IsValueType || propertyType.Name == nameof(String)) + { + propertyNames.Add(property.Name); + } + } + + string namespacePrefix = + namespaceSymbol.IsGlobalNamespace + ? string.Empty + : namespaceSymbol.ToDisplayString(); + + return new( + typeSymbol.Name, + namespacePrefix, + propertyNames.ToImmutableArray()); + } + } + } + } + } + } + + return new(null, null, default); + } + + private readonly struct Target(string? dataType, string? namespacePrefix, ImmutableArray propertyNames) + { + public string? DataType { get; } = dataType; + public string? NamespacePrefix { get; } = namespacePrefix; + public ImmutableArray PropertyNames { get; } = propertyNames; + } +} diff --git a/SourceGenLinq.Generator/SourceGenLinq.Generator.csproj b/SourceGenLinq.Generator/SourceGenLinq.Generator.csproj new file mode 100644 index 0000000..c39ba8a --- /dev/null +++ b/SourceGenLinq.Generator/SourceGenLinq.Generator.csproj @@ -0,0 +1,39 @@ + + + + netstandard2.0 + enable + true + Generated + true + latest + 0.0.1 + SourceGenLinq.Generator + SourceGenLinq.Generator + README.md + Simple implementation of flexible parameterized sorting for IQuariable using IncrementalGenerator + linq;ef-core;ef;sort;order;code-gen;aot; + Apache-2.0 + https://github.com/yurvon-screamo/SourceGenLinq + True + snupkg + + + + + + + + + + + + + + + True + \ + + + + diff --git a/SourceGenLinq.sln b/SourceGenLinq.sln new file mode 100644 index 0000000..b7b8817 --- /dev/null +++ b/SourceGenLinq.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34723.18 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SourceGenLinq.Abstractions", "SourceGenLinq.Abstractions\SourceGenLinq.Abstractions.csproj", "{52A43F0F-5812-41C9-978E-BB5E89AA3916}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SourceGenLinq.Generator", "SourceGenLinq.Generator\SourceGenLinq.Generator.csproj", "{3B085DCD-08D1-44C6-81E5-C228832353C1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample", "Sample\Sample.csproj", "{D365BDF8-0C58-4C02-A912-986C31DBC66B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Элементы решения", "Элементы решения", "{8660DCD0-9359-4C9F-BAC2-3217466DB9C3}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + README.md = README.md + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {52A43F0F-5812-41C9-978E-BB5E89AA3916}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {52A43F0F-5812-41C9-978E-BB5E89AA3916}.Debug|Any CPU.Build.0 = Debug|Any CPU + {52A43F0F-5812-41C9-978E-BB5E89AA3916}.Release|Any CPU.ActiveCfg = Release|Any CPU + {52A43F0F-5812-41C9-978E-BB5E89AA3916}.Release|Any CPU.Build.0 = Release|Any CPU + {3B085DCD-08D1-44C6-81E5-C228832353C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B085DCD-08D1-44C6-81E5-C228832353C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B085DCD-08D1-44C6-81E5-C228832353C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B085DCD-08D1-44C6-81E5-C228832353C1}.Release|Any CPU.Build.0 = Release|Any CPU + {D365BDF8-0C58-4C02-A912-986C31DBC66B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D365BDF8-0C58-4C02-A912-986C31DBC66B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D365BDF8-0C58-4C02-A912-986C31DBC66B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D365BDF8-0C58-4C02-A912-986C31DBC66B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2459D40F-D63A-40A6-949D-6CEB32F15758} + EndGlobalSection +EndGlobal