mirror of
https://github.com/AlexMacocian/SystemExtensions.git
synced 2026-07-21 08:39:29 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1fae173b11 | |||
| a25f2e5acb | |||
| 8e64309c2e | |||
| 24c3e37b5e | |||
| f6435b24ab | |||
| 9118c864bf | |||
| fb84036215 | |||
| f6fd9ec616 | |||
| 6a10fe91e3 | |||
| e890b21bb6 | |||
| e36e6605ff | |||
| 5e8e772d36 | |||
| e6a06915cd | |||
| 3c741ab969 | |||
| a46fde652d | |||
| ecc65a4302 | |||
| 7222528eed | |||
| 41b1b48f98 |
+129
@@ -0,0 +1,129 @@
|
||||
[*.{cs,vb}]
|
||||
|
||||
# IDE0003: Remove qualification
|
||||
dotnet_diagnostic.IDE0003.severity = error
|
||||
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||
tab_width = 4
|
||||
indent_size = 4
|
||||
end_of_line = crlf
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:error
|
||||
dotnet_style_prefer_auto_properties = true:error
|
||||
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:suggestion
|
||||
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||
dotnet_style_prefer_compound_assignment = true:suggestion
|
||||
dotnet_style_prefer_simplified_interpolation = true:suggestion
|
||||
dotnet_style_namespace_match_folder = true:suggestion
|
||||
|
||||
[*.cs]
|
||||
csharp_indent_labels = one_less_than_current
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_using_directive_placement = outside_namespace:error
|
||||
csharp_prefer_simple_using_statement = true:error
|
||||
csharp_prefer_braces = true:silent
|
||||
csharp_style_namespace_declarations = file_scoped:error
|
||||
csharp_style_prefer_method_group_conversion = true:silent
|
||||
csharp_style_expression_bodied_methods = false:silent
|
||||
csharp_style_expression_bodied_constructors = false:silent
|
||||
csharp_style_expression_bodied_operators = false:silent
|
||||
csharp_style_expression_bodied_properties = true:silent
|
||||
csharp_style_expression_bodied_indexers = true:silent
|
||||
csharp_style_expression_bodied_accessors = true:silent
|
||||
csharp_style_expression_bodied_lambdas = true:silent
|
||||
csharp_style_expression_bodied_local_functions = false:silent
|
||||
csharp_style_throw_expression = true:suggestion
|
||||
csharp_style_prefer_null_check_over_type_check = true:suggestion
|
||||
csharp_prefer_simple_default_expression = true:suggestion
|
||||
csharp_style_prefer_local_over_anonymous_function = true:error
|
||||
csharp_style_prefer_index_operator = true:suggestion
|
||||
csharp_style_prefer_range_operator = true:suggestion
|
||||
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
|
||||
csharp_style_prefer_tuple_swap = true:suggestion
|
||||
csharp_style_inlined_variable_declaration = true:suggestion
|
||||
csharp_style_deconstructed_variable_declaration = true:error
|
||||
csharp_style_unused_value_assignment_preference = discard_variable:error
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
|
||||
csharp_prefer_static_local_function = true:suggestion
|
||||
csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
|
||||
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:suggestion
|
||||
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
|
||||
csharp_style_conditional_delegate_call = true:suggestion
|
||||
csharp_style_prefer_parameter_null_checking = true:suggestion
|
||||
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 = true:suggestion
|
||||
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||
csharp_style_var_elsewhere = true:suggestion
|
||||
[*.{cs,vb}]
|
||||
#### Naming styles ####
|
||||
|
||||
# Naming rules
|
||||
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
|
||||
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 = suggestion
|
||||
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 = suggestion
|
||||
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
|
||||
|
||||
# Symbol specifications
|
||||
|
||||
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 =
|
||||
|
||||
# Naming styles
|
||||
|
||||
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
|
||||
dotnet_style_readonly_field = true:suggestion
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
|
||||
dotnet_style_predefined_type_for_member_access = true:silent
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
|
||||
dotnet_style_allow_multiple_blank_lines_experimental = true:silent
|
||||
dotnet_style_allow_statement_immediately_after_block_experimental = false:suggestion
|
||||
dotnet_code_quality_unused_parameters = all:error
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion
|
||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion
|
||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion
|
||||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion
|
||||
dotnet_style_qualification_for_field = true:error
|
||||
dotnet_style_qualification_for_property = true:error
|
||||
dotnet_style_qualification_for_method = true:error
|
||||
dotnet_style_qualification_for_event = true:error
|
||||
@@ -0,0 +1 @@
|
||||
* amacocian@yahoo.com
|
||||
@@ -0,0 +1,16 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
- package-ecosystem: "nuget"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
+13
-22
@@ -26,12 +26,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
@@ -55,26 +55,17 @@ jobs:
|
||||
- name: Build SystemExtensions.NetStandard.Security project
|
||||
run: dotnet build SystemExtensions.NetStandard.Security -c $env:Configuration
|
||||
|
||||
- name: Push SystemExtensions.NetStandard nuget package
|
||||
uses: brandedoutcast/publish-nuget@v2.5.5
|
||||
with:
|
||||
PROJECT_FILE_PATH: SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj
|
||||
NUGET_KEY: ${{secrets.NUGET_API_KEY}}
|
||||
- name: Package SystemExtensions.NetStandard
|
||||
run: dotnet pack -c Release -o . SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj
|
||||
|
||||
- name: Push SystemExtensions.NetCore nuget package
|
||||
uses: brandedoutcast/publish-nuget@v2.5.5
|
||||
with:
|
||||
PROJECT_FILE_PATH: SystemExtensions.NetCore\SystemExtensions.NetCore.csproj
|
||||
NUGET_KEY: ${{secrets.NUGET_API_KEY}}
|
||||
- name: Package SystemExtensions.NetCore
|
||||
run: dotnet pack -c Release -o . SystemExtensions.NetCore\SystemExtensions.NetCore.csproj
|
||||
|
||||
- name: Push SystemExtensions.NetStandard.DependencyInjection nuget package
|
||||
uses: brandedoutcast/publish-nuget@v2.5.5
|
||||
with:
|
||||
PROJECT_FILE_PATH: SystemExtensions.NetStandard.DependencyInjection\SystemExtensions.NetStandard.DependencyInjection.csproj
|
||||
NUGET_KEY: ${{secrets.NUGET_API_KEY}}
|
||||
- name: Package SystemExtensions.NetStandard.DependencyInjection
|
||||
run: dotnet pack -c Release -o . SystemExtensions.NetStandard.DependencyInjection\SystemExtensions.NetStandard.DependencyInjection.csproj
|
||||
|
||||
- name: Push SystemExtensions.NetStandard.Security nuget package
|
||||
uses: brandedoutcast/publish-nuget@v2.5.5
|
||||
with:
|
||||
PROJECT_FILE_PATH: SystemExtensions.NetStandard.Security\SystemExtensions.NetStandard.Security.csproj
|
||||
NUGET_KEY: ${{secrets.NUGET_API_KEY}}
|
||||
- name: Package SystemExtensions.NetStandard.Security
|
||||
run: dotnet pack -c Release -o . SystemExtensions.NetStandard.Security\SystemExtensions.NetStandard.Security.csproj
|
||||
|
||||
- name: Publish
|
||||
run: dotnet nuget push *.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
|
||||
@@ -28,12 +28,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
|
||||
+2
-3
@@ -2,8 +2,8 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Configuration;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration;
|
||||
|
||||
[TestClass]
|
||||
public class DefaultOptionsManagerTests
|
||||
{
|
||||
@@ -23,4 +23,3 @@ namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
this.optionsManager.UpdateOptions(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration;
|
||||
|
||||
public sealed class DummyOptions
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -4,8 +4,8 @@ using Moq;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration;
|
||||
|
||||
[TestClass]
|
||||
public class LiveOptionsResolverTests
|
||||
{
|
||||
@@ -66,4 +66,3 @@ namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
.Returns(this.optionsManagerMock.Object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -4,8 +4,8 @@ using Moq;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration;
|
||||
|
||||
[TestClass]
|
||||
public class LiveUpdateableOptionsResolverTests
|
||||
{
|
||||
@@ -66,4 +66,3 @@ namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
.Returns(this.optionsManagerMock.Object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -3,8 +3,8 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using System.Configuration;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration;
|
||||
|
||||
[TestClass]
|
||||
public class LiveUpdateableOptionsWrapperTests
|
||||
{
|
||||
@@ -41,4 +41,3 @@ namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
this.optionsManagerMock.Verify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,15 @@ using Moq;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration;
|
||||
|
||||
[TestClass]
|
||||
public class OptionsResolverTests
|
||||
{
|
||||
private readonly OptionsResolver optionsResolver = new();
|
||||
private readonly Mock<Slim.IServiceProvider> serviceProviderMock = new();
|
||||
private readonly Mock<IOptionsManager> optionsManagerMock = new();
|
||||
|
||||
public Mock<IOptionsManager> OptionsManagerMock => optionsManagerMock;
|
||||
public Mock<IOptionsManager> OptionsManagerMock { get; } = new();
|
||||
|
||||
[TestMethod]
|
||||
public void CanResolve_ILiveOptions_ReturnsTrue()
|
||||
@@ -69,4 +68,3 @@ namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
.Returns(this.OptionsManagerMock.Object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -4,8 +4,8 @@ using Moq;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration;
|
||||
|
||||
[TestClass]
|
||||
public class UpdateableOptionsResolverTests
|
||||
{
|
||||
@@ -66,4 +66,3 @@ namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
.Returns(this.optionsManagerMock.Object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-4
@@ -5,8 +5,8 @@ using System;
|
||||
using System.Configuration;
|
||||
using System.Extensions.Configuration;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Configuration;
|
||||
|
||||
[TestClass]
|
||||
public class UpdateableOptionsWrapperTests
|
||||
{
|
||||
@@ -18,7 +18,7 @@ namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
[TestInitialize]
|
||||
public void TestInitialize()
|
||||
{
|
||||
this.optionsWrapper = new UpdateableOptionsWrapper<string>(optionsManagerMock.Object, Value);
|
||||
this.optionsWrapper = new UpdateableOptionsWrapper<string>(this.optionsManagerMock.Object, Value);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -45,4 +45,3 @@ namespace SystemExtensions.DependencyInjection.Tests.Configuration
|
||||
this.optionsManagerMock.Verify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Slim;
|
||||
using System;
|
||||
using System.DependencyInjection.Http;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using SystemExtensions.NetStandard.DependencyInjection.Tests.Http.Models;
|
||||
|
||||
namespace SystemExtensions.NetStandard.DependencyInjection.Tests.Http;
|
||||
|
||||
[TestClass]
|
||||
public sealed class HttpClientBuilderTests
|
||||
{
|
||||
private const string SomeHeader = "SomeHeader";
|
||||
private const string SomeValue = "SomeValue";
|
||||
|
||||
private readonly HttpClientBuilder<object> httpClientBuilder;
|
||||
private readonly Mock<IServiceProducer> serviceProducerMock = new();
|
||||
private readonly Uri baseAddress = new("http://contoso.co");
|
||||
|
||||
public HttpClientBuilderTests()
|
||||
{
|
||||
this.httpClientBuilder = new HttpClientBuilder<object>(this.serviceProducerMock.Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Constructor_NullServiceProducer_Throws()
|
||||
{
|
||||
var action = () => new HttpClientBuilder<object>(null);
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WithMessageHandler_NullHandler_Throws()
|
||||
{
|
||||
var action = () => this.httpClientBuilder.WithMessageHandler(null);
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WithBaseAddress_NullBaseAddress_Throws()
|
||||
{
|
||||
var action = () => this.httpClientBuilder.WithBaseAddress(null);
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void WithDefaultRequestHeadersSetup_NullSetup_Throws()
|
||||
{
|
||||
var action = () => this.httpClientBuilder.WithDefaultRequestHeadersSetup(null);
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_ReturnsServiceProducer()
|
||||
{
|
||||
var producer = this.httpClientBuilder.Build();
|
||||
|
||||
producer.Should().Be(this.serviceProducerMock.Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_RegistersWithServiceProducer()
|
||||
{
|
||||
this.serviceProducerMock.Setup(u => u.RegisterScoped(It.IsAny<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false));
|
||||
|
||||
this.httpClientBuilder.Build();
|
||||
|
||||
this.serviceProducerMock.Verify();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_CreatesExpectedClient()
|
||||
{
|
||||
this.serviceProducerMock.Setup(u => u.RegisterScoped(It.IsAny<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false))
|
||||
.Callback<Func<Slim.IServiceProvider, IHttpClient<object>>, bool>((factory, _) =>
|
||||
{
|
||||
var client = factory(new Mock<Slim.IServiceProvider>().Object);
|
||||
client.BaseAddress.Should().BeNull();
|
||||
client.DefaultRequestHeaders.Should().BeEmpty();
|
||||
client.MaxResponseContentBufferSize.Should().Be(2147483647L);
|
||||
client.Timeout.Should().Be(TimeSpan.FromSeconds(100));
|
||||
});
|
||||
|
||||
this.httpClientBuilder.Build();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_WithBaseAddress_ReturnsClientWithBaseAddress()
|
||||
{
|
||||
this.serviceProducerMock.Setup(u => u.RegisterScoped(It.IsAny<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false))
|
||||
.Callback<Func<Slim.IServiceProvider, IHttpClient<object>>, bool>((factory, _) =>
|
||||
{
|
||||
var client = factory(new Mock<Slim.IServiceProvider>().Object);
|
||||
client.BaseAddress.Should().Be(this.baseAddress);
|
||||
});
|
||||
|
||||
this.httpClientBuilder.WithBaseAddress(this.baseAddress)
|
||||
.Build();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_WithDefaultRequestHeaders_CallsFactory()
|
||||
{
|
||||
this.serviceProducerMock.Setup(u => u.RegisterScoped(It.IsAny<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false))
|
||||
.Callback<Func<Slim.IServiceProvider, IHttpClient<object>>, bool>((factory, _) =>
|
||||
{
|
||||
var client = factory(new Mock<Slim.IServiceProvider>().Object);
|
||||
client.DefaultRequestHeaders.TryGetValues(SomeHeader, out var values);
|
||||
|
||||
values.Should().HaveCount(1);
|
||||
values.FirstOrDefault().Should().Be(SomeValue);
|
||||
});
|
||||
|
||||
this.httpClientBuilder.WithDefaultRequestHeadersSetup((headers) =>
|
||||
{
|
||||
headers.TryAddWithoutValidation(SomeHeader, SomeValue);
|
||||
}).Build();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_WithMaxResponseBufferSize_ReturnsClientWithMaxResponseBufferSize()
|
||||
{
|
||||
this.serviceProducerMock.Setup(u => u.RegisterScoped(It.IsAny<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false))
|
||||
.Callback<Func<Slim.IServiceProvider, IHttpClient<object>>, bool>((factory, _) =>
|
||||
{
|
||||
var client = factory(new Mock<Slim.IServiceProvider>().Object);
|
||||
client.MaxResponseContentBufferSize.Should().Be(100);
|
||||
});
|
||||
|
||||
this.httpClientBuilder.WithMaxResponseBufferSize(100)
|
||||
.Build();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_WithTimeout_ReturnsClientWithTimeout()
|
||||
{
|
||||
this.serviceProducerMock.Setup(u => u.RegisterScoped(It.IsAny<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false))
|
||||
.Callback<Func<Slim.IServiceProvider, IHttpClient<object>>, bool>((factory, _) =>
|
||||
{
|
||||
var client = factory(new Mock<Slim.IServiceProvider>().Object);
|
||||
client.Timeout.Should().Be(TimeSpan.FromSeconds(5));
|
||||
});
|
||||
|
||||
this.httpClientBuilder.WithTimeout(TimeSpan.FromSeconds(5))
|
||||
.Build();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Build_WithMessageHandler_CallsMessageHandler()
|
||||
{
|
||||
var handlerMock = new HttpMessageHandlerMock();
|
||||
this.serviceProducerMock.Setup(u => u.RegisterScoped(It.IsAny<Func<Slim.IServiceProvider, IHttpClient<object>>>(), false))
|
||||
.Callback<Func<Slim.IServiceProvider, IHttpClient<object>>, bool>(async (factory, _) =>
|
||||
{
|
||||
var client = factory(new Mock<Slim.IServiceProvider>().Object);
|
||||
await client.GetAsync(this.baseAddress);
|
||||
handlerMock.Called.Should().BeTrue();
|
||||
});
|
||||
|
||||
this.httpClientBuilder.WithMessageHandler(sp => handlerMock)
|
||||
.Build();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task HttpClientBuilder_RegistersClientCorrectly_IServiceProviderReturnsExpected()
|
||||
{
|
||||
var container = new ServiceManager();
|
||||
var messageHandler = new HttpMessageHandlerMock();
|
||||
new HttpClientBuilder<object>(container)
|
||||
.WithBaseAddress(this.baseAddress)
|
||||
.WithDefaultRequestHeadersSetup(header => header.TryAddWithoutValidation(SomeHeader, SomeValue))
|
||||
.WithMaxResponseBufferSize(5)
|
||||
.WithMessageHandler(sp => messageHandler)
|
||||
.WithTimeout(TimeSpan.FromSeconds(5))
|
||||
.Build();
|
||||
|
||||
var client = container.GetService<IHttpClient<object>>();
|
||||
await client.GetAsync("");
|
||||
|
||||
client.Should().NotBeNull();
|
||||
client.BaseAddress.Should().Be(this.baseAddress);
|
||||
client.DefaultRequestHeaders.Should().HaveCount(1);
|
||||
client.DefaultRequestHeaders.First().Key.Should().Be(SomeHeader);
|
||||
client.DefaultRequestHeaders.First().Value.Should().HaveCount(1);
|
||||
client.DefaultRequestHeaders.First().Value.First().Should().Be(SomeValue);
|
||||
client.MaxResponseContentBufferSize.Should().Be(5);
|
||||
client.Timeout.Should().Be(TimeSpan.FromSeconds(5));
|
||||
messageHandler.Called.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,8 @@ using System;
|
||||
using System.Http;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Http
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Http;
|
||||
|
||||
[TestClass]
|
||||
public class HttpClientResolverTests
|
||||
{
|
||||
@@ -66,4 +66,3 @@ namespace SystemExtensions.DependencyInjection.Tests.Http
|
||||
action.Should().Throw<Exception>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemExtensions.NetStandard.DependencyInjection.Tests.Http.Models;
|
||||
public sealed class HttpMessageHandlerMock : HttpMessageHandler
|
||||
{
|
||||
public bool Called { get; private set; }
|
||||
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
this.Called = true;
|
||||
|
||||
return Task.FromResult(new HttpResponseMessage());
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using System.Logging;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Logging
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Logging;
|
||||
|
||||
[TestClass]
|
||||
public class CVLoggerProviderTests
|
||||
{
|
||||
@@ -40,4 +40,3 @@ namespace SystemExtensions.DependencyInjection.Tests.Logging
|
||||
.Verifiable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ using Moq;
|
||||
using System;
|
||||
using System.Logging;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Logging
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Logging;
|
||||
|
||||
[TestClass]
|
||||
public class CVLoggerTests
|
||||
{
|
||||
@@ -73,4 +73,3 @@ namespace SystemExtensions.DependencyInjection.Tests.Logging
|
||||
.Verifiable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Logging;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Logging
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Logging;
|
||||
|
||||
[TestClass]
|
||||
public class DebugLogsWriterTests
|
||||
{
|
||||
@@ -27,4 +27,3 @@ namespace SystemExtensions.DependencyInjection.Tests.Logging
|
||||
action.Should().Throw<Exception>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ using Moq;
|
||||
using System;
|
||||
using System.Logging;
|
||||
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Logging
|
||||
{
|
||||
namespace SystemExtensions.DependencyInjection.Tests.Logging;
|
||||
|
||||
[TestClass]
|
||||
public class LoggerResolverTests
|
||||
{
|
||||
@@ -105,4 +105,3 @@ namespace SystemExtensions.DependencyInjection.Tests.Logging
|
||||
.Returns(this.loggerMock.Object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-6
@@ -7,12 +7,15 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
||||
<PackageReference Include="Moq" Version="4.16.1" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.3" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.0.2" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.9.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="Moq" Version="4.18.2" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
namespace System.Configuration
|
||||
{
|
||||
namespace System.Configuration;
|
||||
|
||||
public sealed class DefaultOptionsManager : IOptionsManager
|
||||
{
|
||||
public T GetOptions<T>() where T : class
|
||||
@@ -11,4 +11,3 @@
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace System.Configuration
|
||||
{
|
||||
namespace System.Configuration;
|
||||
|
||||
public interface ILiveOptions<T> : IOptions<T>
|
||||
where T : class
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,7 +1,6 @@
|
||||
namespace System.Configuration
|
||||
{
|
||||
namespace System.Configuration;
|
||||
|
||||
public interface ILiveUpdateableOptions<T> : ILiveOptions<T>, IUpdateableOptions<T>
|
||||
where T : class
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace System.Configuration
|
||||
{
|
||||
namespace System.Configuration;
|
||||
|
||||
public interface IOptionsManager
|
||||
{
|
||||
T GetOptions<T>()
|
||||
@@ -7,4 +7,3 @@
|
||||
void UpdateOptions<T>(T value)
|
||||
where T : class;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace System.Configuration
|
||||
{
|
||||
namespace System.Configuration;
|
||||
|
||||
public interface IUpdateableOptions<out T> : IOptions<T>
|
||||
where T : class
|
||||
{
|
||||
@@ -10,4 +10,3 @@ namespace System.Configuration
|
||||
/// </summary>
|
||||
void UpdateOption();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
using Slim.Resolvers;
|
||||
|
||||
namespace System.Configuration
|
||||
{
|
||||
namespace System.Configuration;
|
||||
|
||||
public sealed class LiveOptionsResolver : IDependencyResolver
|
||||
{
|
||||
private static readonly Type optionsType = typeof(LiveUpdateableOptionsWrapper<>);
|
||||
@@ -24,4 +24,3 @@ namespace System.Configuration
|
||||
return Activator.CreateInstance(typedOptionsType, configurationManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
using Slim.Resolvers;
|
||||
|
||||
namespace System.Configuration
|
||||
{
|
||||
namespace System.Configuration;
|
||||
|
||||
public sealed class LiveUpdateableOptionsResolver : IDependencyResolver
|
||||
{
|
||||
private static readonly Type optionsType = typeof(LiveUpdateableOptionsWrapper<>);
|
||||
@@ -23,4 +23,3 @@ namespace System.Configuration
|
||||
return Activator.CreateInstance(typedOptionsType, configurationManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
using System.Extensions;
|
||||
|
||||
namespace System.Configuration
|
||||
{
|
||||
namespace System.Configuration;
|
||||
|
||||
public sealed class LiveUpdateableOptionsWrapper<T> : ILiveUpdateableOptions<T>
|
||||
where T : class
|
||||
{
|
||||
@@ -28,4 +28,3 @@ namespace System.Configuration
|
||||
this.configurationManager.UpdateOptions<T>(this.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using Slim.Resolvers;
|
||||
|
||||
namespace System.Configuration
|
||||
{
|
||||
namespace System.Configuration;
|
||||
|
||||
public sealed class OptionsResolver : IDependencyResolver
|
||||
{
|
||||
private static readonly Type optionsType = typeof(OptionsWrapper<>);
|
||||
@@ -30,4 +30,3 @@ namespace System.Configuration
|
||||
return Activator.CreateInstance(typedOptionsType, optionsValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,8 +1,8 @@
|
||||
using Slim.Resolvers;
|
||||
using System.Extensions.Configuration;
|
||||
|
||||
namespace System.Configuration
|
||||
{
|
||||
namespace System.Configuration;
|
||||
|
||||
public sealed class UpdateableOptionsResolver : IDependencyResolver
|
||||
{
|
||||
private static readonly Type optionsType = typeof(UpdateableOptionsWrapper<>);
|
||||
@@ -30,4 +30,3 @@ namespace System.Configuration
|
||||
return Activator.CreateInstance(typedOptionsType, configurationManager, optionsValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace System.Extensions.Configuration
|
||||
{
|
||||
namespace System.Extensions.Configuration;
|
||||
|
||||
public sealed class UpdateableOptionsWrapper<T> : IUpdateableOptions<T>
|
||||
where T : class
|
||||
{
|
||||
@@ -20,4 +20,3 @@ namespace System.Extensions.Configuration
|
||||
this.configurationManager.UpdateOptions(this.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+69
-38
@@ -2,12 +2,13 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using Slim;
|
||||
using System.Configuration;
|
||||
using System.DependencyInjection.Http;
|
||||
using System.Http;
|
||||
using System.Logging;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace System.Extensions
|
||||
{
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class ServiceManagerExtensions
|
||||
{
|
||||
/// <summary>
|
||||
@@ -16,12 +17,14 @@ namespace System.Extensions
|
||||
/// </summary>
|
||||
/// <param name="serviceManager"><see cref="IServiceManager"/>.</param>
|
||||
/// <returns>Provided <see cref="IServiceManager"/>.</returns>
|
||||
public static IServiceManager RegisterOptionsManager(this IServiceManager serviceManager)
|
||||
public static IServiceProducer RegisterOptionsManager(this IServiceProducer serviceProducer)
|
||||
{
|
||||
serviceManager.RegisterSingleton<IOptionsManager, DefaultOptionsManager>();
|
||||
serviceManager.RegisterOptionsResolver();
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
return serviceManager;
|
||||
serviceProducer.RegisterSingleton<IOptionsManager, DefaultOptionsManager>();
|
||||
serviceProducer.RegisterOptionsResolver();
|
||||
|
||||
return serviceProducer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -31,13 +34,15 @@ namespace System.Extensions
|
||||
/// <typeparam name="T">Implementation of <see cref="IOptionsManager"/>.</typeparam>
|
||||
/// <param name="serviceManager"><see cref="IServiceManager"/>.</param>
|
||||
/// <returns>Provided <see cref="IServiceManager"/>.</returns>
|
||||
public static IServiceManager RegisterOptionsManager<T>(this IServiceManager serviceManager)
|
||||
public static IServiceProducer RegisterOptionsManager<T>(this IServiceProducer serviceProducer)
|
||||
where T : IOptionsManager
|
||||
{
|
||||
serviceManager.RegisterSingleton<IOptionsManager, T>();
|
||||
serviceManager.RegisterOptionsResolver();
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
return serviceManager;
|
||||
serviceProducer.RegisterSingleton<IOptionsManager, T>();
|
||||
serviceProducer.RegisterOptionsResolver();
|
||||
|
||||
return serviceProducer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -46,16 +51,16 @@ namespace System.Extensions
|
||||
/// </summary>
|
||||
/// <param name="serviceManager"><see cref="IServiceManager"/>.</param>
|
||||
/// <returns><see cref="IServiceManager"/>.</returns>
|
||||
public static IServiceManager RegisterOptionsResolver(this IServiceManager serviceManager)
|
||||
public static IServiceProducer RegisterOptionsResolver(this IServiceProducer serviceProducer)
|
||||
{
|
||||
serviceManager.ThrowIfNull(nameof(serviceManager));
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
serviceManager.RegisterResolver(new OptionsResolver());
|
||||
serviceManager.RegisterResolver(new UpdateableOptionsResolver());
|
||||
serviceManager.RegisterResolver(new LiveOptionsResolver());
|
||||
serviceManager.RegisterResolver(new LiveUpdateableOptionsResolver());
|
||||
serviceProducer.RegisterResolver(new OptionsResolver());
|
||||
serviceProducer.RegisterResolver(new UpdateableOptionsResolver());
|
||||
serviceProducer.RegisterResolver(new LiveOptionsResolver());
|
||||
serviceProducer.RegisterResolver(new LiveUpdateableOptionsResolver());
|
||||
|
||||
return serviceManager;
|
||||
return serviceProducer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -107,52 +112,78 @@ namespace System.Extensions
|
||||
/// <summary>
|
||||
/// Register a <see cref="ILoggerFactory"/> with a <see cref="CVLoggerProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceManager"></param>
|
||||
/// <param name="serviceProducer"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceManager RegisterCVLoggerFactory(this IServiceManager serviceManager)
|
||||
public static IServiceProducer RegisterCVLoggerFactory(this IServiceProducer serviceProducer)
|
||||
{
|
||||
serviceManager.RegisterScoped<ILoggerFactory, LoggerFactory>(sp =>
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
serviceProducer.RegisterScoped<ILoggerFactory, LoggerFactory>(sp =>
|
||||
{
|
||||
LoggerFactory loggerFactory = new();
|
||||
loggerFactory.AddProvider(new CVLoggerProvider(sp.GetService<ILogsWriter>()));
|
||||
return loggerFactory;
|
||||
});
|
||||
|
||||
return serviceManager;
|
||||
return serviceProducer;
|
||||
}
|
||||
|
||||
public static IServiceManager RegisterLoggerFactory(this IServiceManager serviceManager, Func<Slim.IServiceProvider, ILoggerFactory> loggerFactory)
|
||||
/// <summary>
|
||||
/// Registers a <see cref="ILoggerFactory"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceProducer"><see cref="IServiceProducer"/>.</param>
|
||||
/// <param name="loggerFactory">Factory that produces a <see cref="ILoggerFactory"/>.</param>
|
||||
/// <returns></returns>
|
||||
public static IServiceProducer RegisterLoggerFactory(this IServiceProducer serviceProducer, Func<Slim.IServiceProvider, ILoggerFactory> loggerFactory)
|
||||
{
|
||||
serviceManager.ThrowIfNull(nameof(serviceManager));
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
serviceManager.RegisterSingleton<ILoggerFactory, ILoggerFactory>(loggerFactory);
|
||||
return serviceManager;
|
||||
serviceProducer.RegisterSingleton<ILoggerFactory, ILoggerFactory>(loggerFactory);
|
||||
return serviceProducer;
|
||||
}
|
||||
|
||||
public static IServiceManager RegisterDebugLoggerFactory(this IServiceManager serviceManager)
|
||||
/// <summary>
|
||||
/// Registers a <see cref="ILoggerFactory"/> with a <see cref="ILogsWriter"/> that writes to <see cref="Diagnostics.Debug"/>.
|
||||
/// </summary>
|
||||
/// <param name="serviceProducer"><see cref="IServiceProducer"/>.</param>
|
||||
/// <returns></returns>
|
||||
public static IServiceProducer RegisterDebugLoggerFactory(this IServiceProducer serviceProducer)
|
||||
{
|
||||
serviceManager.ThrowIfNull(nameof(serviceManager));
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
serviceManager.RegisterLogWriter<ILogsWriter, DebugLogsWriter>();
|
||||
return serviceManager;
|
||||
serviceProducer.RegisterLogWriter<ILogsWriter, DebugLogsWriter>();
|
||||
return serviceProducer;
|
||||
}
|
||||
|
||||
public static IServiceManager RegisterHttpFactory(this IServiceManager serviceManager)
|
||||
/// <summary>
|
||||
/// Register a scoped <see cref="IHttpClient{TScope}"/> to be used by the DI engine.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the scoped <see cref="IHttpClient{TScope}"/>.</typeparam>
|
||||
/// <param name="serviceProducer"><see cref="IServiceProducer"/>.</param>
|
||||
/// <returns><see cref="HttpClientBuilder{T}"/> to build the http client.</returns>
|
||||
public static HttpClientBuilder<T> RegisterHttpClient<T>(this IServiceProducer serviceProducer)
|
||||
{
|
||||
serviceManager.ThrowIfNull(nameof(serviceManager));
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
serviceManager.RegisterResolver(new HttpClientResolver());
|
||||
return serviceManager;
|
||||
return new HttpClientBuilder<T>(serviceProducer);
|
||||
}
|
||||
|
||||
public static IServiceManager RegisterHttpFactory(this IServiceManager serviceManager, Func<Slim.IServiceProvider, Type, HttpMessageHandler> handlerFactory)
|
||||
[Obsolete($"{nameof(RegisterHttpFactory)} is obsolete. Please use {nameof(RegisterHttpClient)} for each service that requires an instance of {nameof(IHttpClient<object>)}.")]
|
||||
public static IServiceProducer RegisterHttpFactory(this IServiceProducer serviceProducer)
|
||||
{
|
||||
serviceManager.ThrowIfNull(nameof(serviceManager));
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
serviceManager.RegisterResolver(
|
||||
serviceProducer.RegisterResolver(new HttpClientResolver());
|
||||
return serviceProducer;
|
||||
}
|
||||
[Obsolete($"{nameof(RegisterHttpFactory)} is obsolete. Please use {nameof(RegisterHttpClient)} for each service that requires an instance of {nameof(IHttpClient<object>)}.")]
|
||||
public static IServiceProducer RegisterHttpFactory(this IServiceProducer serviceProducer, Func<Slim.IServiceProvider, Type, HttpMessageHandler> handlerFactory)
|
||||
{
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
serviceProducer.RegisterResolver(
|
||||
new HttpClientResolver()
|
||||
.WithHttpMessageHandlerFactory(handlerFactory));
|
||||
return serviceManager;
|
||||
}
|
||||
return serviceProducer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("SystemExtensions.NetStandard.DependencyInjection.Tests")]
|
||||
@@ -0,0 +1,85 @@
|
||||
using Slim;
|
||||
using System.Extensions;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
namespace System.DependencyInjection.Http;
|
||||
|
||||
public sealed class HttpClientBuilder<T>
|
||||
{
|
||||
private readonly IServiceProducer serviceProducer;
|
||||
|
||||
private Uri baseAddress;
|
||||
private Func<IServiceProvider, HttpMessageHandler> httpMessageHandlerFactory;
|
||||
private bool disposeMessageHandler;
|
||||
private Action<HttpRequestHeaders> defaultRequestHeadersSetup;
|
||||
private long maxResponseBufferSize = 2147483647L; //2GB default HttpClient value [https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.maxresponsecontentbuffersize?view=net-6.0]
|
||||
private TimeSpan timeout = TimeSpan.FromSeconds(100); //100 seconds default HttpClient value [https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.timeout?view=net-6.0]
|
||||
|
||||
internal HttpClientBuilder(IServiceProducer serviceProducer)
|
||||
{
|
||||
serviceProducer.ThrowIfNull(nameof(serviceProducer));
|
||||
|
||||
this.serviceProducer = serviceProducer;
|
||||
}
|
||||
|
||||
public HttpClientBuilder<T> WithMessageHandler(Func<IServiceProvider, HttpMessageHandler> httpMessageHandlerFactory)
|
||||
{
|
||||
httpMessageHandlerFactory.ThrowIfNull(nameof(httpMessageHandlerFactory));
|
||||
|
||||
this.httpMessageHandlerFactory = httpMessageHandlerFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpClientBuilder<T> WithDisposeMessageHandler(bool disposeMessageHandler)
|
||||
{
|
||||
this.disposeMessageHandler = disposeMessageHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpClientBuilder<T> WithBaseAddress(Uri baseAddress)
|
||||
{
|
||||
baseAddress.ThrowIfNull(nameof(baseAddress));
|
||||
|
||||
this.baseAddress = baseAddress;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpClientBuilder<T> WithDefaultRequestHeadersSetup(Action<HttpRequestHeaders> setup)
|
||||
{
|
||||
setup.ThrowIfNull(nameof(setup));
|
||||
|
||||
this.defaultRequestHeadersSetup = setup;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpClientBuilder<T> WithMaxResponseBufferSize(long responseBufferSize)
|
||||
{
|
||||
this.maxResponseBufferSize = responseBufferSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HttpClientBuilder<T> WithTimeout(TimeSpan timeout)
|
||||
{
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IServiceProducer Build()
|
||||
{
|
||||
this.serviceProducer.RegisterScoped<IHttpClient<T>>(sp =>
|
||||
{
|
||||
var client = this.httpMessageHandlerFactory is not null ?
|
||||
new HttpClient<T>(this.httpMessageHandlerFactory(sp), this.disposeMessageHandler) :
|
||||
new HttpClient<T>();
|
||||
|
||||
client.BaseAddress = this.baseAddress;
|
||||
this.defaultRequestHeadersSetup?.Invoke(client.DefaultRequestHeaders);
|
||||
client.MaxResponseContentBufferSize = this.maxResponseBufferSize;
|
||||
client.Timeout = this.timeout;
|
||||
return client;
|
||||
});
|
||||
|
||||
return this.serviceProducer;
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,9 @@
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace System.Http
|
||||
{
|
||||
namespace System.Http;
|
||||
|
||||
[Obsolete($"Please use {nameof(Extensions.ServiceManagerExtensions.RegisterHttpClient)} for each use case of {nameof(IHttpClient<object>)}")]
|
||||
public sealed class HttpClientResolver : IDependencyResolver
|
||||
{
|
||||
private static readonly Type clientType = typeof(HttpClient<>);
|
||||
@@ -44,4 +45,3 @@ namespace System.Http
|
||||
return httpClient;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Extensions;
|
||||
|
||||
namespace System.Logging
|
||||
{
|
||||
namespace System.Logging;
|
||||
|
||||
public sealed class CVLogger : ILogger
|
||||
{
|
||||
private readonly string category;
|
||||
@@ -41,4 +41,3 @@ namespace System.Logging
|
||||
this.cvLoggerProvider.LogEntry(log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Extensions;
|
||||
|
||||
namespace System.Logging
|
||||
{
|
||||
namespace System.Logging;
|
||||
|
||||
public sealed class CVLoggerProvider : ICVLoggerProvider
|
||||
{
|
||||
private readonly ILogsWriter logsManager;
|
||||
@@ -36,4 +36,3 @@ namespace System.Logging
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.Logging
|
||||
{
|
||||
namespace System.Logging;
|
||||
|
||||
public sealed class DebugLogsWriter : ILogsWriter
|
||||
{
|
||||
public void WriteLog(Log log)
|
||||
@@ -9,4 +9,3 @@ namespace System.Logging
|
||||
Debug.WriteLine($"{log.LogTime} - {log.Category} - {log.EventId} - {log.CorrelationVector} - {log.LogLevel} - {log.Message}{Environment.NewLine}{log.Exception}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace System.Logging
|
||||
{
|
||||
namespace System.Logging;
|
||||
|
||||
public interface ICVLoggerProvider : ILoggerProvider
|
||||
{
|
||||
void LogEntry(Log log);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
namespace System.Logging
|
||||
{
|
||||
namespace System.Logging;
|
||||
|
||||
public interface ILogsWriter
|
||||
{
|
||||
void WriteLog(Log log);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
using Slim.Resolvers;
|
||||
using System.Linq;
|
||||
|
||||
namespace System.Logging
|
||||
{
|
||||
namespace System.Logging;
|
||||
|
||||
public sealed class LoggerResolver : IDependencyResolver
|
||||
{
|
||||
public bool CanResolve(Type type)
|
||||
@@ -47,4 +47,3 @@ namespace System.Logging
|
||||
return loggerFactory.CreateLogger(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace System.Logging
|
||||
{
|
||||
namespace System.Logging;
|
||||
|
||||
public sealed record Log
|
||||
{
|
||||
public Exception Exception { get; set; }
|
||||
@@ -12,4 +12,3 @@ namespace System.Logging
|
||||
public string Message { get; set; }
|
||||
public string CorrelationVector { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using System.Net.Http;
|
||||
|
||||
namespace System.DependencyInjection.Models;
|
||||
|
||||
internal sealed class TypedHttpClientFactory<T>
|
||||
{
|
||||
public Func<Slim.IServiceProvider, HttpMessageHandler> Factory { get; set; }
|
||||
}
|
||||
+3
-3
@@ -6,7 +6,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Version>1.1.7</Version>
|
||||
<Version>1.2.3</Version>
|
||||
<Authors>Alexandru Macocian</Authors>
|
||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||
<Description>Extensions for the Slim Dependency Injection engine</Description>
|
||||
@@ -22,8 +22,8 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CorrelationVector" Version="1.0.42" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||
<PackageReference Include="Slim" Version="1.6.0" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.3.1" />
|
||||
<PackageReference Include="Slim" Version="1.9.2" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -7,8 +7,8 @@ using System.Security.Encryption;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Tests
|
||||
{
|
||||
namespace SystemExtensions.NetStandard.Security.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class AesEncrypterTests
|
||||
{
|
||||
@@ -102,4 +102,3 @@ namespace SystemExtensions.NetStandard.Security.Tests
|
||||
encryptionStream.Should().BeAssignableTo<CryptoStream>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Linq;
|
||||
using System.Security.Rng;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Tests
|
||||
{
|
||||
namespace SystemExtensions.NetStandard.Security.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class CryptoRngProviderTests
|
||||
{
|
||||
@@ -52,4 +52,3 @@ namespace SystemExtensions.NetStandard.Security.Tests
|
||||
bytes.Length.Should().Be(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
-21
@@ -4,8 +4,8 @@ using System;
|
||||
using System.Security.Hashing;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Tests
|
||||
{
|
||||
namespace SystemExtensions.NetStandard.Security.Tests;
|
||||
|
||||
[TestClass]
|
||||
public sealed class Rfc2898DeriveBytesPasswordHashingServiceTests
|
||||
{
|
||||
@@ -47,126 +47,126 @@ namespace SystemExtensions.NetStandard.Security.Tests
|
||||
{
|
||||
var action = new Func<Task<byte[]>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(null, this.saltBytes, DesiredHashLength, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
action.Should().ThrowAsync<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void PasswordNull_HashString_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<string>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(null, this.saltString, DesiredHashLength, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
action.Should().ThrowAsync<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void SaltNull_HashBytes_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<byte[]>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, null, DesiredHashLength, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
action.Should().ThrowAsync<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void SaltNull_HashString_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<string>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, null, DesiredHashLength, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
action.Should().ThrowAsync<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void HashLengthTooSmall_HashBytes_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<byte[]>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, this.saltBytes, TooShortHashLength, Iterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
action.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void HashLengthTooSmall_HashString_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<string>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, this.saltString, TooShortHashLength, Iterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
action.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void TooLittleIterations_HashBytes_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<byte[]>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, this.saltBytes, DesiredHashLength, TooLittleIterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
action.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void TooLittleIterations_HashString_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<string>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, this.saltString, DesiredHashLength, TooLittleIterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
action.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void TooShortSalt_HashBytes_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<byte[]>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordBytes, this.tooShortSaltBytes, DesiredHashLength, TooLittleIterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
action.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void TooShortSalt_HashString_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<string>>(() => this.rfc2898DeriveBytesPasswordHashingService.Hash(this.passwordString, this.tooShortSaltString, DesiredHashLength, TooLittleIterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
action.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void PasswordNull_VerifyBytes_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(null, this.incorrectPasswordBytes, this.saltBytes, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
action.Should().ThrowAsync<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void PasswordNull_VerifyString_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(null, this.incorrectPasswordString, this.saltString, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
action.Should().ThrowAsync<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void HashNull_VerifyBytes_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(this.passwordBytes, null, this.saltBytes, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
action.Should().ThrowAsync<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void HashNull_VerifyString_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(this.passwordString, null, this.saltString, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
action.Should().ThrowAsync<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void SaltNull_VerifyBytes_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(this.passwordBytes, this.incorrectPasswordBytes, null, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
action.Should().ThrowAsync<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void SaltNull_VerifyString_Throws_ArgumentNullException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(this.passwordString, this.incorrectPasswordString, null, Iterations));
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
action.Should().ThrowAsync<ArgumentNullException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void TooLittleIterations_VerifyBytes_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(this.passwordBytes, this.incorrectPasswordBytes, this.saltBytes, TooLittleIterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
action.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public void TooLittleIterations_VerifyString_Throws_InvalidOperationException()
|
||||
{
|
||||
var action = new Func<Task<bool>>(() => this.rfc2898DeriveBytesPasswordHashingService.VerifyPassword(this.passwordString, this.incorrectPasswordString, this.saltString, TooLittleIterations));
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
action.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
[TestMethod]
|
||||
public async Task HashBytes_ReturnsHashedBytes()
|
||||
@@ -258,4 +258,3 @@ namespace SystemExtensions.NetStandard.Security.Tests
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Security.Encryption;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Tests
|
||||
{
|
||||
namespace SystemExtensions.NetStandard.Security.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class SecureStringTests
|
||||
{
|
||||
@@ -119,4 +119,3 @@ namespace SystemExtensions.NetStandard.Security.Tests
|
||||
ss1.Should().Be(ss2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ using System.Security.Hashing;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Security.Tests
|
||||
{
|
||||
namespace SystemExtensions.NetStandard.Security.Tests;
|
||||
|
||||
[TestClass]
|
||||
public sealed class Sha256HashingServiceTests
|
||||
{
|
||||
@@ -45,4 +45,3 @@ namespace SystemExtensions.NetStandard.Security.Tests
|
||||
hash.Should().BeAssignableTo<Stream>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-5
@@ -7,11 +7,14 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.3" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.0.2" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.9.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -4,73 +4,85 @@ using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using System.Security.Utilities;
|
||||
|
||||
namespace System.Security.Encryption
|
||||
namespace System.Security.Encryption;
|
||||
|
||||
public sealed class AesEncrypter : ISymmetricEncrypter, IDisposable
|
||||
{
|
||||
public sealed class AesEncrypter : ISymmetricEncrypter
|
||||
private readonly Aes aes;
|
||||
|
||||
public AesEncrypter()
|
||||
{
|
||||
this.aes = Aes.Create();
|
||||
}
|
||||
|
||||
public AesEncrypter(Aes aes)
|
||||
{
|
||||
this.aes = aes;
|
||||
}
|
||||
|
||||
public async Task<string> Decrypt(string key, string iv, string value)
|
||||
{
|
||||
using var valueStream = BytesToStream(StringToBytes(value));
|
||||
using var decryptedStream = await DecryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
using var decryptedStream = await this.DecryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
return StreamToString(decryptedStream);
|
||||
}
|
||||
|
||||
public async Task<string> Decrypt(byte[] key, byte[] iv, string value)
|
||||
{
|
||||
using var valueStream = BytesToStream(StringToBytes(value));
|
||||
using var decryptedStream = await DecryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
using var decryptedStream = await this.DecryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
return StreamToString(decryptedStream);
|
||||
}
|
||||
|
||||
public async Task<byte[]> Decrypt(string key, string iv, byte[] value)
|
||||
{
|
||||
using var valueStream = BytesToStream(value);
|
||||
using var decryptedStream = await DecryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
using var decryptedStream = await this.DecryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
return StreamToBytes(decryptedStream);
|
||||
}
|
||||
|
||||
public async Task<byte[]> Decrypt(byte[] key, byte[] iv, byte[] value)
|
||||
{
|
||||
using var valueStream = BytesToStream(value);
|
||||
using var decryptedStream = await DecryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
using var decryptedStream = await this.DecryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
return StreamToBytes(decryptedStream);
|
||||
}
|
||||
|
||||
public async Task<Stream> Decrypt(string key, string iv, Stream value)
|
||||
{
|
||||
return await DecryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
|
||||
return await this.DecryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<Stream> Decrypt(byte[] key, byte[] iv, Stream value)
|
||||
{
|
||||
return await DecryptInternal(key, iv, value).ConfigureAwait(false);
|
||||
return await this.DecryptInternal(key, iv, value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<string> Encrypt(string key, string iv, string value)
|
||||
{
|
||||
using var valueStream = BytesToStream(StringToBytes(value));
|
||||
using var encryptedStream = await EncryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
using var encryptedStream = await this.EncryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
return StreamToString(encryptedStream);
|
||||
}
|
||||
|
||||
public async Task<string> Encrypt(byte[] key, byte[] iv, string value)
|
||||
{
|
||||
using var valueStream = BytesToStream(StringToBytes(value));
|
||||
using var encryptedStream = await EncryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
using var encryptedStream = await this.EncryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
return StreamToString(encryptedStream);
|
||||
}
|
||||
|
||||
public async Task<byte[]> Encrypt(string key, string iv, byte[] value)
|
||||
{
|
||||
using var valueStream = BytesToStream(value);
|
||||
using var encryptedStream = await EncryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
using var encryptedStream = await this.EncryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
|
||||
return StreamToBytes(encryptedStream);
|
||||
}
|
||||
|
||||
public async Task<byte[]> Encrypt(byte[] key, byte[] iv, byte[] value)
|
||||
{
|
||||
using var valueStream = BytesToStream(value);
|
||||
using var encryptedStream = await EncryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
using var encryptedStream = await this.EncryptInternal(key, iv, valueStream).ConfigureAwait(false);
|
||||
return StreamToBytes(encryptedStream);
|
||||
}
|
||||
|
||||
@@ -78,34 +90,104 @@ namespace System.Security.Encryption
|
||||
{
|
||||
return value is null
|
||||
? throw new ArgumentNullException(nameof(value))
|
||||
: await EncryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
|
||||
: await this.EncryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<Stream> Encrypt(byte[] key, byte[] iv, Stream value)
|
||||
{
|
||||
return value is null
|
||||
? throw new ArgumentNullException(nameof(value))
|
||||
: await EncryptInternal(key, iv, value).ConfigureAwait(false);
|
||||
: await this.EncryptInternal(key, iv, value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Stream GetEncryptionStream(string key, string iv, Stream outStream)
|
||||
{
|
||||
return GetEncryptionStreamInternal(StringToBytes(key), StringToBytes(iv), outStream);
|
||||
return this.GetEncryptionStreamInternal(StringToBytes(key), StringToBytes(iv), outStream);
|
||||
}
|
||||
|
||||
public Stream GetEncryptionStream(byte[] key, byte[] iv, Stream outStream)
|
||||
{
|
||||
return GetEncryptionStreamInternal(key, iv, outStream);
|
||||
return this.GetEncryptionStreamInternal(key, iv, outStream);
|
||||
}
|
||||
|
||||
public Stream GetDecryptionStream(string key, string iv, Stream inStream)
|
||||
{
|
||||
return GetDecryptionStreamInternal(StringToBytes(key), StringToBytes(iv), inStream);
|
||||
return this.GetDecryptionStreamInternal(StringToBytes(key), StringToBytes(iv), inStream);
|
||||
}
|
||||
|
||||
public Stream GetDecryptionStream(byte[] key, byte[] iv, Stream inStream)
|
||||
{
|
||||
return GetDecryptionStreamInternal(key, iv, inStream);
|
||||
return this.GetDecryptionStreamInternal(key, iv, inStream);
|
||||
}
|
||||
|
||||
private async Task<Stream> EncryptInternal(byte[] key, byte[] iv, Stream toEncryptStream)
|
||||
{
|
||||
if (key.Length < 32)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(key)} must be at least 32 bytes");
|
||||
}
|
||||
|
||||
if (iv.Length < 16)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(iv)} must be at least 16 bytes");
|
||||
}
|
||||
|
||||
key = key.Take(32).ToArray();
|
||||
iv = iv.Take(16).ToArray();
|
||||
|
||||
|
||||
var encryptedMemoryStream = new MemoryStream();
|
||||
using var cryptoStream = this.GetEncryptionStreamInternal(key, iv, encryptedMemoryStream);
|
||||
await toEncryptStream.CopyToAsync(cryptoStream).ConfigureAwait(false);
|
||||
if (!cryptoStream.HasFlushedFinalBlock)
|
||||
{
|
||||
cryptoStream.FlushFinalBlock();
|
||||
}
|
||||
|
||||
encryptedMemoryStream.Position = 0;
|
||||
return encryptedMemoryStream;
|
||||
}
|
||||
|
||||
private async Task<Stream> DecryptInternal(byte[] key, byte[] iv, Stream toDecryptStream)
|
||||
{
|
||||
if (key.Length < 32)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(key)} must be at least 32 bytes");
|
||||
}
|
||||
|
||||
if (iv.Length < 16)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(iv)} must be at least 16 bytes");
|
||||
}
|
||||
|
||||
key = key.Take(32).ToArray();
|
||||
iv = iv.Take(16).ToArray();
|
||||
|
||||
|
||||
var decryptedMemoryStream = new MemoryStream();
|
||||
using var cryptoStream = this.GetDecryptionStreamInternal(key, iv, toDecryptStream);
|
||||
await cryptoStream.CopyToAsync(decryptedMemoryStream).ConfigureAwait(false);
|
||||
if (!cryptoStream.HasFlushedFinalBlock)
|
||||
{
|
||||
cryptoStream.FlushFinalBlock();
|
||||
}
|
||||
|
||||
decryptedMemoryStream.Position = 0;
|
||||
return decryptedMemoryStream;
|
||||
}
|
||||
|
||||
private CryptoStream GetEncryptionStreamInternal(byte[] key, byte[] iv, Stream encryptedStream)
|
||||
{
|
||||
var crypto = this.aes.CreateEncryptor(key, iv);
|
||||
var cryptoStream = new NotClosingCryptoStream(encryptedStream, crypto, CryptoStreamMode.Write);
|
||||
return cryptoStream;
|
||||
}
|
||||
|
||||
private CryptoStream GetDecryptionStreamInternal(byte[] key, byte[] iv, Stream encryptedStream)
|
||||
{
|
||||
var crypto = this.aes.CreateDecryptor(key, iv);
|
||||
var cryptoStream = new NotClosingCryptoStream(encryptedStream, crypto, CryptoStreamMode.Read);
|
||||
return cryptoStream;
|
||||
}
|
||||
|
||||
private static byte[] StreamToBytes(Stream value)
|
||||
@@ -137,78 +219,8 @@ namespace System.Security.Encryption
|
||||
return new MemoryStream(value);
|
||||
}
|
||||
|
||||
private static async Task<Stream> EncryptInternal(byte[] key, byte[] iv, Stream toEncryptStream)
|
||||
public void Dispose()
|
||||
{
|
||||
if (key.Length < 32)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(key)} must be at least 32 bytes");
|
||||
}
|
||||
|
||||
if (iv.Length < 16)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(iv)} must be at least 16 bytes");
|
||||
}
|
||||
|
||||
key = key.Take(32).ToArray();
|
||||
iv = iv.Take(16).ToArray();
|
||||
|
||||
|
||||
var encryptedMemoryStream = new MemoryStream();
|
||||
using var cryptoStream = GetEncryptionStreamInternal(key, iv, encryptedMemoryStream);
|
||||
await toEncryptStream.CopyToAsync(cryptoStream).ConfigureAwait(false);
|
||||
if (!cryptoStream.HasFlushedFinalBlock)
|
||||
{
|
||||
cryptoStream.FlushFinalBlock();
|
||||
}
|
||||
|
||||
encryptedMemoryStream.Position = 0;
|
||||
return encryptedMemoryStream;
|
||||
}
|
||||
|
||||
private static async Task<Stream> DecryptInternal(byte[] key, byte[] iv, Stream toDecryptStream)
|
||||
{
|
||||
if (key.Length < 32)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(key)} must be at least 32 bytes");
|
||||
}
|
||||
|
||||
if (iv.Length < 16)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(iv)} must be at least 16 bytes");
|
||||
}
|
||||
|
||||
key = key.Take(32).ToArray();
|
||||
iv = iv.Take(16).ToArray();
|
||||
|
||||
|
||||
var decryptedMemoryStream = new MemoryStream();
|
||||
using var cryptoStream = GetDecryptionStreamInternal(key, iv, toDecryptStream);
|
||||
await cryptoStream.CopyToAsync(decryptedMemoryStream).ConfigureAwait(false);
|
||||
if (!cryptoStream.HasFlushedFinalBlock)
|
||||
{
|
||||
cryptoStream.FlushFinalBlock();
|
||||
}
|
||||
|
||||
decryptedMemoryStream.Position = 0;
|
||||
return decryptedMemoryStream;
|
||||
}
|
||||
|
||||
private static CryptoStream GetEncryptionStreamInternal(byte[] key, byte[] iv, Stream encryptedStream)
|
||||
{
|
||||
using var aes = Aes.Create();
|
||||
aes.Padding = PaddingMode.PKCS7;
|
||||
var crypto = aes.CreateEncryptor(key, iv);
|
||||
var cryptoStream = new NotClosingCryptoStream(encryptedStream, crypto, CryptoStreamMode.Write);
|
||||
return cryptoStream;
|
||||
}
|
||||
|
||||
private static CryptoStream GetDecryptionStreamInternal(byte[] key, byte[] iv, Stream encryptedStream)
|
||||
{
|
||||
using var aes = Aes.Create();
|
||||
aes.Padding = PaddingMode.PKCS7;
|
||||
var crypto = aes.CreateDecryptor(key, iv);
|
||||
var cryptoStream = new NotClosingCryptoStream(encryptedStream, crypto, CryptoStreamMode.Read);
|
||||
return cryptoStream;
|
||||
}
|
||||
this.aes.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Security.Encryption
|
||||
{
|
||||
namespace System.Security.Encryption;
|
||||
|
||||
public interface ISymmetricEncrypter
|
||||
{
|
||||
Stream GetEncryptionStream(string key, string iv, Stream outStream);
|
||||
@@ -22,4 +22,3 @@ namespace System.Security.Encryption
|
||||
Task<Stream> Decrypt(string key, string iv, Stream value);
|
||||
Task<Stream> Decrypt(byte[] key, byte[] iv, Stream value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Security.Encryption
|
||||
{
|
||||
namespace System.Security.Encryption;
|
||||
|
||||
public sealed class SecureString
|
||||
{
|
||||
private static byte[] optionalEntropy;
|
||||
@@ -99,4 +99,3 @@ namespace System.Security.Encryption
|
||||
optionalEntropy = entropy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Security.Hashing
|
||||
{
|
||||
namespace System.Security.Hashing;
|
||||
|
||||
public interface IHashingService
|
||||
{
|
||||
Task<string> Hash(string raw);
|
||||
Task<byte[]> Hash(byte[] raw);
|
||||
Task<Stream> Hash(Stream raw);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Security.Hashing
|
||||
{
|
||||
namespace System.Security.Hashing;
|
||||
|
||||
public interface IPasswordHashingService
|
||||
{
|
||||
/// <summary>
|
||||
@@ -44,4 +44,3 @@ namespace System.Security.Hashing
|
||||
/// <returns>Returns true if password matches the previously hashed password. Otherwise returns false.</returns>
|
||||
Task<bool> VerifyPassword(byte[] hash, byte[] password, byte[] salt, int iterations);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,8 +1,8 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Security.Hashing
|
||||
{
|
||||
namespace System.Security.Hashing;
|
||||
|
||||
public sealed class Rfc2898DeriveBytesPasswordHashingService : IPasswordHashingService
|
||||
{
|
||||
private const int MinimumIterations = 10000;
|
||||
@@ -98,4 +98,3 @@ namespace System.Security.Hashing
|
||||
return Task.FromResult(match && hash.Length.Equals(hashToVerify.Length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Security.Hashing
|
||||
{
|
||||
namespace System.Security.Hashing;
|
||||
|
||||
public sealed class Sha256HashingService : IHashingService
|
||||
{
|
||||
public async Task<string> Hash(string raw)
|
||||
@@ -59,4 +59,3 @@ namespace System.Security.Hashing
|
||||
return await Task.Run(() => new MemoryStream(sha256.ComputeHash(raw)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace System.Security.Rng
|
||||
{
|
||||
namespace System.Security.Rng;
|
||||
|
||||
public sealed class CryptoRngProvider : ICryptoRngProvider, IDisposable
|
||||
{
|
||||
private readonly RNGCryptoServiceProvider rngProvider;
|
||||
@@ -56,4 +56,3 @@ namespace System.Security.Rng
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace System.Security.Rng
|
||||
{
|
||||
namespace System.Security.Rng;
|
||||
|
||||
public interface ICryptoRngProvider
|
||||
{
|
||||
/// <summary>
|
||||
@@ -25,4 +25,3 @@
|
||||
/// <returns>Array containing cryptographically secure random non-zero values.</returns>
|
||||
public byte[] GetNonZeroBytes(int byteCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<RootNamespace>System</RootNamespace>
|
||||
<Version>1.2.3</Version>
|
||||
<Version>1.2.5</Version>
|
||||
<Authors>Alexandru Macocian</Authors>
|
||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||
<Description>Security extensions for the System namespace</Description>
|
||||
@@ -21,7 +21,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="5.0.0" />
|
||||
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="7.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace System.Security.Utilities
|
||||
{
|
||||
namespace System.Security.Utilities;
|
||||
|
||||
internal sealed class NotClosingCryptoStream : CryptoStream
|
||||
{
|
||||
public NotClosingCryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
|
||||
@@ -20,4 +20,3 @@ namespace System.Security.Utilities
|
||||
base.Dispose(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
namespace System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// AVL tree implementation.
|
||||
/// Thanks to Karim Oumghar for the implementation example.
|
||||
@@ -35,13 +35,13 @@ namespace System.Collections.Generic
|
||||
{
|
||||
get
|
||||
{
|
||||
return count;
|
||||
return this.count;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// True if the collection is readonly. False otherwise.
|
||||
/// </summary>
|
||||
public bool IsReadOnly => isReadOnly;
|
||||
public bool IsReadOnly => this.isReadOnly;
|
||||
#endregion
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
@@ -59,15 +59,15 @@ namespace System.Collections.Generic
|
||||
/// <param name="value">Value to be added to the tree.</param>
|
||||
public void Add(T value)
|
||||
{
|
||||
count++;
|
||||
this.count++;
|
||||
var newItem = new AVLNode<T>(value);
|
||||
if (root == null)
|
||||
if (this.root == null)
|
||||
{
|
||||
root = newItem;
|
||||
this.root = newItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
root = RecursiveInsertion(root, newItem);
|
||||
this.root = this.RecursiveInsertion(this.root, newItem);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
@@ -77,11 +77,12 @@ namespace System.Collections.Generic
|
||||
/// <returns>True if the value is in the tree.</returns>
|
||||
public bool Contains(T value)
|
||||
{
|
||||
var node = Find(value, root);
|
||||
var node = this.Find(value, this.root);
|
||||
if (node == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node.Value.CompareTo(value) == 0)
|
||||
{
|
||||
return true;
|
||||
@@ -97,7 +98,7 @@ namespace System.Collections.Generic
|
||||
/// <param name="value">Value to be deleted.</param>
|
||||
public bool Remove(T value)
|
||||
{
|
||||
root = Delete(root, value);
|
||||
this.root = this.Delete(this.root, value);
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -106,7 +107,7 @@ namespace System.Collections.Generic
|
||||
public void Clear()
|
||||
{
|
||||
var queue = new Queue<AVLNode<T>>();
|
||||
queue.Enqueue(root);
|
||||
queue.Enqueue(this.root);
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
@@ -115,17 +116,19 @@ namespace System.Collections.Generic
|
||||
{
|
||||
queue.Enqueue(currentNode.Left);
|
||||
currentNode.Left = null;
|
||||
count--;
|
||||
this.count--;
|
||||
}
|
||||
|
||||
if (currentNode.Right != null)
|
||||
{
|
||||
queue.Enqueue(currentNode.Right);
|
||||
currentNode.Right = null;
|
||||
count--;
|
||||
this.count--;
|
||||
}
|
||||
}
|
||||
root = null;
|
||||
count--;
|
||||
|
||||
this.root = null;
|
||||
this.count--;
|
||||
}
|
||||
/// <summary>
|
||||
/// Copies the tree onto the provided array.
|
||||
@@ -135,7 +138,7 @@ namespace System.Collections.Generic
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
var queue = new Queue<AVLNode<T>>();
|
||||
queue.Enqueue(root);
|
||||
queue.Enqueue(this.root);
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
var currentNode = queue.Dequeue();
|
||||
@@ -144,6 +147,7 @@ namespace System.Collections.Generic
|
||||
{
|
||||
queue.Enqueue(currentNode.Left);
|
||||
}
|
||||
|
||||
if (currentNode.Right != null)
|
||||
{
|
||||
queue.Enqueue(currentNode.Right);
|
||||
@@ -156,7 +160,7 @@ namespace System.Collections.Generic
|
||||
/// <returns></returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return GetEnumerator(root);
|
||||
return this.GetEnumerator(this.root);
|
||||
}
|
||||
/// <summary>
|
||||
/// Copies the tree structure into an array.
|
||||
@@ -164,8 +168,8 @@ namespace System.Collections.Generic
|
||||
/// <returns>Array containing the values contained in the tree.</returns>
|
||||
public T[] ToArray()
|
||||
{
|
||||
var array = new T[count];
|
||||
CopyTo(array, 0);
|
||||
var array = new T[this.count];
|
||||
this.CopyTo(array, 0);
|
||||
return array;
|
||||
}
|
||||
#endregion
|
||||
@@ -179,41 +183,43 @@ namespace System.Collections.Generic
|
||||
}
|
||||
else if (n.Value.CompareTo(current.Value) < 0)
|
||||
{
|
||||
current.Left = RecursiveInsertion(current.Left, n);
|
||||
current = BalanceTree(current);
|
||||
current.Left = this.RecursiveInsertion(current.Left, n);
|
||||
current = this.BalanceTree(current);
|
||||
}
|
||||
else if (n.Value.CompareTo(current.Value) > 0)
|
||||
{
|
||||
current.Right = RecursiveInsertion(current.Right, n);
|
||||
current = BalanceTree(current);
|
||||
current.Right = this.RecursiveInsertion(current.Right, n);
|
||||
current = this.BalanceTree(current);
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
private AVLNode<T> BalanceTree(AVLNode<T> current)
|
||||
{
|
||||
var b_factor = BalanceFactor(current);
|
||||
var b_factor = this.BalanceFactor(current);
|
||||
if (b_factor > 1)
|
||||
{
|
||||
if (BalanceFactor(current.Left) > 0)
|
||||
if (this.BalanceFactor(current.Left) > 0)
|
||||
{
|
||||
current = RotateLL(current);
|
||||
current = this.RotateLL(current);
|
||||
}
|
||||
else
|
||||
{
|
||||
current = RotateLR(current);
|
||||
current = this.RotateLR(current);
|
||||
}
|
||||
}
|
||||
else if (b_factor < -1)
|
||||
{
|
||||
if (BalanceFactor(current.Right) > 0)
|
||||
if (this.BalanceFactor(current.Right) > 0)
|
||||
{
|
||||
current = RotateRL(current);
|
||||
current = this.RotateRL(current);
|
||||
}
|
||||
else
|
||||
{
|
||||
current = RotateRR(current);
|
||||
current = this.RotateRR(current);
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
private AVLNode<T> Delete(AVLNode<T> current, T target)
|
||||
@@ -226,39 +232,39 @@ namespace System.Collections.Generic
|
||||
//left subtree
|
||||
if (target.CompareTo(current.Value) < 0)
|
||||
{
|
||||
current.Left = Delete(current.Left, target);
|
||||
if (BalanceFactor(current) == -2)//here
|
||||
current.Left = this.Delete(current.Left, target);
|
||||
if (this.BalanceFactor(current) == -2)//here
|
||||
{
|
||||
if (BalanceFactor(current.Right) <= 0)
|
||||
if (this.BalanceFactor(current.Right) <= 0)
|
||||
{
|
||||
current = RotateRR(current);
|
||||
current = this.RotateRR(current);
|
||||
}
|
||||
else
|
||||
{
|
||||
current = RotateRL(current);
|
||||
current = this.RotateRL(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
//right subtree
|
||||
else if (target.CompareTo(current.Value) > 0)
|
||||
{
|
||||
current.Right = Delete(current.Right, target);
|
||||
if (BalanceFactor(current) == 2)
|
||||
current.Right = this.Delete(current.Right, target);
|
||||
if (this.BalanceFactor(current) == 2)
|
||||
{
|
||||
if (BalanceFactor(current.Left) >= 0)
|
||||
if (this.BalanceFactor(current.Left) >= 0)
|
||||
{
|
||||
current = RotateLL(current);
|
||||
current = this.RotateLL(current);
|
||||
}
|
||||
else
|
||||
{
|
||||
current = RotateLR(current);
|
||||
current = this.RotateLR(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
//if target is found
|
||||
else
|
||||
{
|
||||
count--;
|
||||
this.count--;
|
||||
if (current.Right != null)
|
||||
{
|
||||
//delete its inorder successor
|
||||
@@ -267,15 +273,16 @@ namespace System.Collections.Generic
|
||||
{
|
||||
parent = parent.Left;
|
||||
}
|
||||
|
||||
current.Value = parent.Value;
|
||||
current.Right = Delete(current.Right, parent.Value);
|
||||
if (BalanceFactor(current) == 2)//rebalancing
|
||||
current.Right = this.Delete(current.Right, parent.Value);
|
||||
if (this.BalanceFactor(current) == 2)//rebalancing
|
||||
{
|
||||
if (BalanceFactor(current.Left) >= 0)
|
||||
if (this.BalanceFactor(current.Left) >= 0)
|
||||
{
|
||||
current = RotateLL(current);
|
||||
current = this.RotateLL(current);
|
||||
}
|
||||
else { current = RotateLR(current); }
|
||||
else { current = this.RotateLR(current); }
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -284,6 +291,7 @@ namespace System.Collections.Generic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
private AVLNode<T> Find(T target, AVLNode<T> current)
|
||||
@@ -292,6 +300,7 @@ namespace System.Collections.Generic
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (target.CompareTo(current.Value) < 0)
|
||||
{
|
||||
if (target.CompareTo(current.Value) == 0)
|
||||
@@ -300,7 +309,7 @@ namespace System.Collections.Generic
|
||||
}
|
||||
else
|
||||
{
|
||||
return Find(target, current.Left);
|
||||
return this.Find(target, current.Left);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -311,10 +320,9 @@ namespace System.Collections.Generic
|
||||
}
|
||||
else
|
||||
{
|
||||
return Find(target, current.Right);
|
||||
return this.Find(target, current.Right);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private int Max(int l, int r)
|
||||
{
|
||||
@@ -325,17 +333,18 @@ namespace System.Collections.Generic
|
||||
var height = 0;
|
||||
if (current != null)
|
||||
{
|
||||
var l = GetHeight(current.Left);
|
||||
var r = GetHeight(current.Right);
|
||||
var m = Max(l, r);
|
||||
var l = this.GetHeight(current.Left);
|
||||
var r = this.GetHeight(current.Right);
|
||||
var m = this.Max(l, r);
|
||||
height = m + 1;
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
private int BalanceFactor(AVLNode<T> current)
|
||||
{
|
||||
var l = GetHeight(current.Left);
|
||||
var r = GetHeight(current.Right);
|
||||
var l = this.GetHeight(current.Left);
|
||||
var r = this.GetHeight(current.Right);
|
||||
var b_factor = l - r;
|
||||
return b_factor;
|
||||
}
|
||||
@@ -356,14 +365,14 @@ namespace System.Collections.Generic
|
||||
private AVLNode<T> RotateLR(AVLNode<T> parent)
|
||||
{
|
||||
var pivot = parent.Left;
|
||||
parent.Left = RotateRR(pivot);
|
||||
return RotateLL(parent);
|
||||
parent.Left = this.RotateRR(pivot);
|
||||
return this.RotateLL(parent);
|
||||
}
|
||||
private AVLNode<T> RotateRL(AVLNode<T> parent)
|
||||
{
|
||||
var pivot = parent.Right;
|
||||
parent.Right = RotateLL(pivot);
|
||||
return RotateRR(parent);
|
||||
parent.Right = this.RotateLL(pivot);
|
||||
return this.RotateRR(parent);
|
||||
}
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
@@ -382,6 +391,7 @@ namespace System.Collections.Generic
|
||||
{
|
||||
queue.Enqueue(currentNode.Left);
|
||||
}
|
||||
|
||||
if (currentNode.Right != null)
|
||||
{
|
||||
queue.Enqueue(currentNode.Right);
|
||||
@@ -390,4 +400,3 @@ namespace System.Collections.Generic
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
namespace System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Binary heap implementation.
|
||||
/// </summary>
|
||||
@@ -23,7 +23,7 @@ namespace System.Collections.Generic
|
||||
{
|
||||
get
|
||||
{
|
||||
return items[1];
|
||||
return this.items[1];
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
@@ -33,7 +33,7 @@ namespace System.Collections.Generic
|
||||
{
|
||||
get
|
||||
{
|
||||
return items[count];
|
||||
return this.items[this.count];
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
@@ -41,20 +41,20 @@ namespace System.Collections.Generic
|
||||
/// </summary>
|
||||
public int Capacity
|
||||
{
|
||||
get => capacity;
|
||||
get => this.capacity;
|
||||
set
|
||||
{
|
||||
if (value > capacity)
|
||||
if (value > this.capacity)
|
||||
{
|
||||
Array.Resize(ref items, value);
|
||||
capacity = value;
|
||||
Array.Resize(ref this.items, value);
|
||||
this.capacity = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Number of elements in the heap.
|
||||
/// </summary>
|
||||
public int Count { get => count; }
|
||||
public int Count { get => this.count; }
|
||||
#endregion
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
@@ -62,9 +62,9 @@ namespace System.Collections.Generic
|
||||
/// </summary>
|
||||
public BinaryHeap()
|
||||
{
|
||||
capacity = 10;
|
||||
initialCapacity = capacity;
|
||||
items = new T[capacity];
|
||||
this.capacity = 10;
|
||||
this.initialCapacity = this.capacity;
|
||||
this.items = new T[this.capacity];
|
||||
}
|
||||
/// <summary>
|
||||
/// Constructor for a binary heap data structure.
|
||||
@@ -73,8 +73,8 @@ namespace System.Collections.Generic
|
||||
public BinaryHeap(int capacity)
|
||||
{
|
||||
this.capacity = capacity;
|
||||
initialCapacity = capacity;
|
||||
items = new T[capacity];
|
||||
this.initialCapacity = capacity;
|
||||
this.items = new T[capacity];
|
||||
}
|
||||
#endregion
|
||||
#region Public Methods
|
||||
@@ -84,16 +84,18 @@ namespace System.Collections.Generic
|
||||
/// <param name="value">Value to be added.</param>
|
||||
public void Add(T value)
|
||||
{
|
||||
if (count == Capacity - 1)
|
||||
if (this.count == this.Capacity - 1)
|
||||
{
|
||||
Capacity = 2 * Capacity;
|
||||
this.Capacity = 2 * this.Capacity;
|
||||
}
|
||||
var position = ++count;
|
||||
for (; position > 1 && value.CompareTo(items[position / 2]) < 0; position /= 2)
|
||||
|
||||
var position = ++this.count;
|
||||
for (; position > 1 && value.CompareTo(this.items[position / 2]) < 0; position /= 2)
|
||||
{
|
||||
items[position] = items[position / 2];
|
||||
this.items[position] = this.items[position / 2];
|
||||
}
|
||||
items[position] = value;
|
||||
|
||||
this.items[position] = value;
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes the item at the root. Throws exception if there are no items in the heap.
|
||||
@@ -101,13 +103,14 @@ namespace System.Collections.Generic
|
||||
/// <returns>Value removed.</returns>
|
||||
public T Remove()
|
||||
{
|
||||
if (count == 0)
|
||||
if (this.count == 0)
|
||||
{
|
||||
throw new IndexOutOfRangeException("Heap is empty!");
|
||||
}
|
||||
var min = items[1];
|
||||
items[1] = items[count--];
|
||||
BubbleDown(1);
|
||||
|
||||
var min = this.items[1];
|
||||
this.items[1] = this.items[this.count--];
|
||||
this.BubbleDown(1);
|
||||
return min;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -116,11 +119,12 @@ namespace System.Collections.Generic
|
||||
/// <returns></returns>
|
||||
public T Peek()
|
||||
{
|
||||
if (count == 0)
|
||||
if (this.count == 0)
|
||||
{
|
||||
throw new IndexOutOfRangeException("Heap is empty!");
|
||||
}
|
||||
var min = items[1];
|
||||
|
||||
var min = this.items[1];
|
||||
return min;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -129,8 +133,8 @@ namespace System.Collections.Generic
|
||||
/// <returns>Array with values sorted as in heap</returns>
|
||||
public T[] ToArray()
|
||||
{
|
||||
var newArray = new T[count];
|
||||
Array.Copy(items, 1, newArray, 0, count);
|
||||
var newArray = new T[this.count];
|
||||
Array.Copy(this.items, 1, newArray, 0, this.count);
|
||||
return newArray;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -140,14 +144,14 @@ namespace System.Collections.Generic
|
||||
/// <returns></returns>
|
||||
public bool Contains(T value)
|
||||
{
|
||||
return items.Contains(value);
|
||||
return this.items.Contains(value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Clears the heap
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
count = 0;
|
||||
this.count = 0;
|
||||
}
|
||||
/// <summary>
|
||||
/// Clears the heap.
|
||||
@@ -155,11 +159,11 @@ namespace System.Collections.Generic
|
||||
/// <param name="completeClear">Specifies if the underlying array should be cleared as well</param>
|
||||
public void Clear(bool completeClear)
|
||||
{
|
||||
count = 0;
|
||||
this.count = 0;
|
||||
if (completeClear)
|
||||
{
|
||||
capacity = initialCapacity;
|
||||
items = new T[initialCapacity];
|
||||
this.capacity = this.initialCapacity;
|
||||
this.items = new T[this.initialCapacity];
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
@@ -168,9 +172,9 @@ namespace System.Collections.Generic
|
||||
/// <returns>Enumerator that iterates over the heap.</returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < count; i++)
|
||||
for (var i = 0; i < this.count; i++)
|
||||
{
|
||||
yield return items[i + 1];
|
||||
yield return this.items[i + 1];
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -181,25 +185,27 @@ namespace System.Collections.Generic
|
||||
/// <param name="index">Index of element to bubble</param>
|
||||
private void BubbleDown(int index)
|
||||
{
|
||||
var temp = items[index];
|
||||
var temp = this.items[index];
|
||||
int childIndex;
|
||||
for (; 2 * index <= count; index = childIndex)
|
||||
for (; 2 * index <= this.count; index = childIndex)
|
||||
{
|
||||
childIndex = 2 * index;
|
||||
if (childIndex != Count && items[childIndex].CompareTo(items[childIndex + 1]) > 0)
|
||||
if (childIndex != this.Count && this.items[childIndex].CompareTo(this.items[childIndex + 1]) > 0)
|
||||
{
|
||||
childIndex++;
|
||||
}
|
||||
if (temp.CompareTo(items[childIndex]) > 0)
|
||||
|
||||
if (temp.CompareTo(this.items[childIndex]) > 0)
|
||||
{
|
||||
items[index] = items[childIndex];
|
||||
this.items[index] = this.items[childIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
items[index] = temp;
|
||||
|
||||
this.items[index] = temp;
|
||||
}
|
||||
/// <summary>
|
||||
/// Implementation of IEnumerator.
|
||||
@@ -211,4 +217,3 @@ namespace System.Collections.Generic
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
namespace System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Fibonacci Heap implementation.
|
||||
/// </summary>
|
||||
@@ -19,7 +19,7 @@
|
||||
{
|
||||
get
|
||||
{
|
||||
return count;
|
||||
return this.count;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
@@ -29,7 +29,7 @@
|
||||
{
|
||||
get
|
||||
{
|
||||
return root.Value;
|
||||
return this.root.Value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -58,8 +58,8 @@
|
||||
Degree = 0
|
||||
};
|
||||
node.Previous = node.Next = node;
|
||||
root = this.Merge(root, node);
|
||||
count++;
|
||||
this.root = this.Merge(this.root, node);
|
||||
this.count++;
|
||||
}
|
||||
/// <summary>
|
||||
/// Merge current heap with another heap. The other heap will be disposed at the end of this method.
|
||||
@@ -67,9 +67,9 @@
|
||||
/// <param name="otherHeap">The heap to be merged with the current heap.</param>
|
||||
public void Merge(FibonacciHeap<T> otherHeap)
|
||||
{
|
||||
root = Merge(root, otherHeap.root);
|
||||
this.root = this.Merge(this.root, otherHeap.root);
|
||||
otherHeap.root = null;
|
||||
count += otherHeap.count;
|
||||
this.count += otherHeap.count;
|
||||
}
|
||||
/// <summary>
|
||||
/// Remove the minimum value from the heap.
|
||||
@@ -77,11 +77,11 @@
|
||||
/// <returns>Minimum value.</returns>
|
||||
public T Remove()
|
||||
{
|
||||
var currentRoot = root;
|
||||
var currentRoot = this.root;
|
||||
if (currentRoot != null)
|
||||
{
|
||||
root = RemoveMinimum(root);
|
||||
count--;
|
||||
this.root = this.RemoveMinimum(this.root);
|
||||
this.count--;
|
||||
return currentRoot.Value;
|
||||
}
|
||||
else
|
||||
@@ -96,8 +96,8 @@
|
||||
/// <param name="value">New value to be assigned to the node.</param>
|
||||
public void DecreaseKey(T oldValue, T value)
|
||||
{
|
||||
var node = Find(root, oldValue);
|
||||
root = DecreaseKey(root, node, value);
|
||||
var node = this.Find(this.root, oldValue);
|
||||
this.root = this.DecreaseKey(this.root, node, value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Determines whether the heap contains a specified value.
|
||||
@@ -106,17 +106,17 @@
|
||||
/// <returns></returns>
|
||||
public bool Contains(T value)
|
||||
{
|
||||
return Find(root, value) != null;
|
||||
return this.Find(this.root, value) != null;
|
||||
}
|
||||
/// <summary>
|
||||
/// Clears the heap.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
count = 0;
|
||||
Remove(root);
|
||||
root.Next = root.Previous = root.Parent = root.Child = null;
|
||||
root = null;
|
||||
this.count = 0;
|
||||
this.Remove(this.root);
|
||||
this.root.Next = this.root.Previous = this.root.Parent = this.root.Child = null;
|
||||
this.root = null;
|
||||
}
|
||||
/// <summary>
|
||||
/// Return the heap structure as an array. Array is not sorted other than the
|
||||
@@ -125,20 +125,21 @@
|
||||
/// <returns>Array with values from the heap.</returns>
|
||||
public T[] ToArray()
|
||||
{
|
||||
if (count == 0)
|
||||
if (this.count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var array = new T[count];
|
||||
if (count == 1)
|
||||
|
||||
var array = new T[this.count];
|
||||
if (this.count == 1)
|
||||
{
|
||||
array[0] = root.Value;
|
||||
array[0] = this.root.Value;
|
||||
return array;
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = 0;
|
||||
RecursiveFillArray(root, ref array, ref index);
|
||||
this.RecursiveFillArray(this.root, ref array, ref index);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@@ -148,7 +149,7 @@
|
||||
/// <returns>Enumerator that iterates over the heap.</returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return GetEnumerator(root);
|
||||
return this.GetEnumerator(this.root);
|
||||
}
|
||||
#endregion
|
||||
#region Private Methods
|
||||
@@ -167,8 +168,9 @@
|
||||
index++;
|
||||
if (currentNode.HasChildren())
|
||||
{
|
||||
RecursiveFillArray(currentNode.Child, ref array, ref index);
|
||||
this.RecursiveFillArray(currentNode.Child, ref array, ref index);
|
||||
}
|
||||
|
||||
currentNode = currentNode.Previous;
|
||||
} while (currentNode != oldNode);
|
||||
}
|
||||
@@ -191,10 +193,10 @@
|
||||
{
|
||||
queue.Enqueue(currentNode.Child);
|
||||
}
|
||||
|
||||
currentNode = currentNode.Previous;
|
||||
} while (currentNode != oldNode);
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// Recursively remove the node and its children from the heap.
|
||||
@@ -207,11 +209,12 @@
|
||||
var current = node;
|
||||
do
|
||||
{
|
||||
Remove(current.Child);
|
||||
this.Remove(current.Child);
|
||||
if (current.Parent != null)
|
||||
{
|
||||
current.Parent.Child = null;
|
||||
}
|
||||
|
||||
current = current.Next;
|
||||
} while (current != node);
|
||||
current.Next = current.Previous = current.Child = current.Parent = null;
|
||||
@@ -228,16 +231,19 @@
|
||||
{
|
||||
return node2;
|
||||
}
|
||||
|
||||
if (node2 == null)
|
||||
{
|
||||
return node1;
|
||||
}
|
||||
|
||||
if (node1.Value.CompareTo(node2.Value) > 0)
|
||||
{
|
||||
var temp = node1;
|
||||
node1 = node2;
|
||||
node2 = temp;
|
||||
}
|
||||
|
||||
var node1Next = node1.Next;
|
||||
var node2Prev = node2.Previous;
|
||||
node1.Next = node2;
|
||||
@@ -256,7 +262,7 @@
|
||||
child.Previous = child.Next = child;
|
||||
child.Parent = parent;
|
||||
parent.Degree++;
|
||||
parent.Child = Merge(parent.Child, child);
|
||||
parent.Child = this.Merge(parent.Child, child);
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes the parent of the specified node.
|
||||
@@ -268,6 +274,7 @@
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var current = node;
|
||||
do
|
||||
{
|
||||
@@ -283,7 +290,7 @@
|
||||
/// <returns></returns>
|
||||
private FibonacciNode<T> RemoveMinimum(FibonacciNode<T> node)
|
||||
{
|
||||
RemoveParent(node.Child);
|
||||
this.RemoveParent(node.Child);
|
||||
if (node.Next == node)
|
||||
{
|
||||
node = node.Child;
|
||||
@@ -292,8 +299,9 @@
|
||||
{
|
||||
node.Next.Previous = node.Previous;
|
||||
node.Previous.Next = node.Next;
|
||||
node = Merge(node.Next, node.Child);
|
||||
node = this.Merge(node.Next, node.Child);
|
||||
}
|
||||
|
||||
if (node == null)
|
||||
{
|
||||
return node;
|
||||
@@ -309,12 +317,13 @@
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
trees[node.Degree] = null;
|
||||
if (node.Value.CompareTo(t.Value) < 0)
|
||||
{
|
||||
t.Previous.Next = t.Next;
|
||||
t.Next.Previous = t.Previous;
|
||||
AddChild(node, t);
|
||||
this.AddChild(node, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -323,7 +332,7 @@
|
||||
if (node.Next == node)
|
||||
{
|
||||
t.Next = t.Previous = t;
|
||||
AddChild(t, node);
|
||||
this.AddChild(t, node);
|
||||
node = t;
|
||||
}
|
||||
else
|
||||
@@ -332,18 +341,21 @@
|
||||
node.Next.Previous = t;
|
||||
t.Next = node.Next;
|
||||
t.Previous = node.Previous;
|
||||
AddChild(t, node);
|
||||
this.AddChild(t, node);
|
||||
node = t;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
trees[node.Degree] = node;
|
||||
}
|
||||
|
||||
node = node.Next;
|
||||
}
|
||||
|
||||
var min = node;
|
||||
var start = node;
|
||||
do
|
||||
@@ -352,6 +364,7 @@
|
||||
{
|
||||
min = node;
|
||||
}
|
||||
|
||||
node = node.Next;
|
||||
} while (node != start);
|
||||
return min;
|
||||
@@ -374,9 +387,10 @@
|
||||
node.Previous.Next = node.Next;
|
||||
node.Parent.Child = node.Next;
|
||||
}
|
||||
|
||||
node.Next = node.Previous = node;
|
||||
node.Marked = false;
|
||||
return Merge(root, node);
|
||||
return this.Merge(root, node);
|
||||
}
|
||||
/// <summary>
|
||||
/// Decrease value of provided node substituting it with the provided value.
|
||||
@@ -391,21 +405,23 @@
|
||||
{
|
||||
return root;
|
||||
}
|
||||
|
||||
node.Value = value;
|
||||
if (node.Parent != null)
|
||||
{
|
||||
if (node.Value.CompareTo(node.Parent.Value) < 0)
|
||||
{
|
||||
root = Cut(root, node);
|
||||
root = this.Cut(root, node);
|
||||
var parent = node.Parent;
|
||||
node.Parent = null;
|
||||
while (parent != null && parent.Marked)
|
||||
{
|
||||
root = Cut(root, parent);
|
||||
root = this.Cut(root, parent);
|
||||
node = parent;
|
||||
parent = node.Parent;
|
||||
node.Parent = null;
|
||||
}
|
||||
|
||||
if (parent != null && parent.Parent != null)
|
||||
{
|
||||
parent.Marked = true;
|
||||
@@ -419,6 +435,7 @@
|
||||
root = node;
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -434,17 +451,20 @@
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (node.Value.CompareTo(value) == 0)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
var ret = Find(node.Child, value);
|
||||
|
||||
var ret = this.Find(node.Child, value);
|
||||
if (ret != null)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
node = node.Next;
|
||||
} while (node != root);
|
||||
return null;
|
||||
@@ -472,62 +492,62 @@
|
||||
{
|
||||
get
|
||||
{
|
||||
return previous;
|
||||
return this.previous;
|
||||
}
|
||||
set
|
||||
{
|
||||
previous = value;
|
||||
this.previous = value;
|
||||
}
|
||||
}
|
||||
public FibonacciNode<T> Next
|
||||
{
|
||||
get
|
||||
{
|
||||
return next;
|
||||
return this.next;
|
||||
}
|
||||
set
|
||||
{
|
||||
next = value;
|
||||
this.next = value;
|
||||
}
|
||||
}
|
||||
public FibonacciNode<T> Child
|
||||
{
|
||||
get
|
||||
{
|
||||
return child;
|
||||
return this.child;
|
||||
}
|
||||
set
|
||||
{
|
||||
child = value;
|
||||
this.child = value;
|
||||
}
|
||||
}
|
||||
public FibonacciNode<T> Parent
|
||||
{
|
||||
get
|
||||
{
|
||||
return parent;
|
||||
return this.parent;
|
||||
}
|
||||
set
|
||||
{
|
||||
parent = value;
|
||||
this.parent = value;
|
||||
}
|
||||
}
|
||||
public bool Marked
|
||||
{
|
||||
get
|
||||
{
|
||||
return marked;
|
||||
return this.marked;
|
||||
}
|
||||
set
|
||||
{
|
||||
marked = value;
|
||||
this.marked = value;
|
||||
}
|
||||
}
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return value;
|
||||
return this.value;
|
||||
}
|
||||
set
|
||||
{
|
||||
@@ -538,23 +558,22 @@
|
||||
{
|
||||
get
|
||||
{
|
||||
return degree;
|
||||
return this.degree;
|
||||
}
|
||||
set
|
||||
{
|
||||
degree = value;
|
||||
this.degree = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Public Methods
|
||||
public bool HasChildren()
|
||||
{
|
||||
return child != null;
|
||||
return this.child != null;
|
||||
}
|
||||
public bool HasParent()
|
||||
{
|
||||
return parent != null;
|
||||
return this.parent != null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
namespace System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for queue implementations.
|
||||
/// </summary>
|
||||
@@ -36,4 +36,3 @@
|
||||
/// <returns>True if queue contains provided item. False otherwise.</returns>
|
||||
bool Contains(T item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
namespace System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Priority Queue data structure. The implementation is based on an array-based implementation of Binary Heap.
|
||||
/// Exposes some of the functionality of the Binary Heap as a queue.
|
||||
@@ -19,7 +19,7 @@
|
||||
{
|
||||
get
|
||||
{
|
||||
return binaryHeap.Count;
|
||||
return this.binaryHeap.Count;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -29,7 +29,7 @@
|
||||
/// </summary>
|
||||
public PriorityQueue()
|
||||
{
|
||||
binaryHeap = new BinaryHeap<T>();
|
||||
this.binaryHeap = new BinaryHeap<T>();
|
||||
}
|
||||
#endregion
|
||||
#region Public Methods
|
||||
@@ -39,7 +39,7 @@
|
||||
/// <param name="value">Value to be added to the queue.</param>
|
||||
public void Enqueue(T value)
|
||||
{
|
||||
binaryHeap.Add(value);
|
||||
this.binaryHeap.Add(value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Pops the queue and removes the highest priority value from the queue.
|
||||
@@ -47,9 +47,9 @@
|
||||
/// <returns>Highest priority value from the queue</returns>
|
||||
public T Dequeue()
|
||||
{
|
||||
if (Count > 0)
|
||||
if (this.Count > 0)
|
||||
{
|
||||
return binaryHeap.Remove();
|
||||
return this.binaryHeap.Remove();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -62,14 +62,14 @@
|
||||
/// <returns>Highest priority value from the queue.</returns>
|
||||
public T Peek()
|
||||
{
|
||||
return binaryHeap.Min;
|
||||
return this.binaryHeap.Min;
|
||||
}
|
||||
/// <summary>
|
||||
/// Clears the queue contents, removing any value stored into the queue.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
binaryHeap.Clear();
|
||||
this.binaryHeap.Clear();
|
||||
}
|
||||
/// <summary>
|
||||
/// Checks if queue contains provided item.
|
||||
@@ -78,7 +78,7 @@
|
||||
/// <returns>True if queue contains the provided item. False otherwise.</returns>
|
||||
public bool Contains(T item)
|
||||
{
|
||||
return binaryHeap.Contains(item);
|
||||
return this.binaryHeap.Contains(item);
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns an enumerator that iterates over the queue.
|
||||
@@ -86,7 +86,7 @@
|
||||
/// <returns>Enumerator that iterates over the queue.</returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return binaryHeap.GetEnumerator();
|
||||
return this.binaryHeap.GetEnumerator();
|
||||
}
|
||||
#endregion
|
||||
#region Private Methods
|
||||
@@ -100,4 +100,3 @@
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
namespace System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Skip list implementation.
|
||||
/// </summary>
|
||||
@@ -19,7 +19,7 @@
|
||||
{
|
||||
this.Key = key;
|
||||
this.Level = level;
|
||||
Next = new NodeSet<TKey>[level + 1];
|
||||
this.Next = new NodeSet<TKey>[level + 1];
|
||||
}
|
||||
}
|
||||
private int count;
|
||||
@@ -33,7 +33,7 @@
|
||||
/// <summary>
|
||||
/// Number of elements in the list.
|
||||
/// </summary>
|
||||
public int Count { get => count; }
|
||||
public int Count { get => this.count; }
|
||||
/// <summary>
|
||||
/// Specifies if the collection can be modified.
|
||||
/// </summary>
|
||||
@@ -47,12 +47,12 @@
|
||||
public SkipList(int maxLevel = 10)
|
||||
{
|
||||
this.maxLevel = maxLevel;
|
||||
random = new Random();
|
||||
head = new NodeSet<T>(default, maxLevel);
|
||||
end = head;
|
||||
this.random = new Random();
|
||||
this.head = new NodeSet<T>(default, maxLevel);
|
||||
this.end = this.head;
|
||||
for (var i = 0; i <= maxLevel; i++)
|
||||
{
|
||||
head.Next[i] = end;
|
||||
this.head.Next[i] = this.end;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,31 +64,36 @@
|
||||
/// <param name="item">Item to be added.</param>
|
||||
public void Add(T item)
|
||||
{
|
||||
var curNode = head;
|
||||
var curNode = this.head;
|
||||
var newLevel = 0;
|
||||
while (random.Next(0, 2) > 0 && newLevel < maxLevel)
|
||||
while (this.random.Next(0, 2) > 0 && newLevel < this.maxLevel)
|
||||
{
|
||||
newLevel++;
|
||||
}
|
||||
if (newLevel > level)
|
||||
|
||||
if (newLevel > this.level)
|
||||
{
|
||||
level = newLevel;
|
||||
this.level = newLevel;
|
||||
}
|
||||
|
||||
var newNode = new NodeSet<T>(item, newLevel);
|
||||
for (var i = 0; i <= newLevel; i++)
|
||||
{
|
||||
if (i > curNode.Level)
|
||||
{
|
||||
curNode = head;
|
||||
curNode = this.head;
|
||||
}
|
||||
while (curNode.Next[i] != end && curNode.Next[i].Key.CompareTo(item) < 0)
|
||||
|
||||
while (curNode.Next[i] != this.end && curNode.Next[i].Key.CompareTo(item) < 0)
|
||||
{
|
||||
curNode = curNode.Next[i];
|
||||
}
|
||||
|
||||
newNode.Next[i] = curNode.Next[i];
|
||||
curNode.Next[i] = newNode;
|
||||
}
|
||||
count++;
|
||||
|
||||
this.count++;
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes provided item from the collection.
|
||||
@@ -98,17 +103,19 @@
|
||||
public bool Remove(T item)
|
||||
{
|
||||
var removed = false;
|
||||
var curNode = head;
|
||||
for (var i = 0; i <= maxLevel; i++)
|
||||
var curNode = this.head;
|
||||
for (var i = 0; i <= this.maxLevel; i++)
|
||||
{
|
||||
if (i > curNode.Level)
|
||||
{
|
||||
curNode = head;
|
||||
curNode = this.head;
|
||||
}
|
||||
while (curNode.Next[i] != end && curNode.Next[i].Key.CompareTo(item) < 0)
|
||||
|
||||
while (curNode.Next[i] != this.end && curNode.Next[i].Key.CompareTo(item) < 0)
|
||||
{
|
||||
curNode = curNode.Next[i];
|
||||
}
|
||||
|
||||
if (curNode.Next[i].Key.CompareTo(item) == 0) //Item is present on this level
|
||||
{
|
||||
curNode.Next[i] = curNode.Next[i].Next[i];
|
||||
@@ -119,9 +126,10 @@
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (removed)
|
||||
{
|
||||
count--;
|
||||
this.count--;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -134,11 +142,12 @@
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
for (var i = 0; i < maxLevel; i++)
|
||||
for (var i = 0; i < this.maxLevel; i++)
|
||||
{
|
||||
head.Next[i] = end;
|
||||
this.head.Next[i] = this.end;
|
||||
}
|
||||
count = 0;
|
||||
|
||||
this.count = 0;
|
||||
}
|
||||
/// <summary>
|
||||
/// Checks if item is present in the collection.
|
||||
@@ -147,10 +156,11 @@
|
||||
/// <returns>True if item is present in the collection.</returns>
|
||||
public bool Contains(T item)
|
||||
{
|
||||
if (Find(item) != null)
|
||||
if (this.Find(item) != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -160,8 +170,8 @@
|
||||
/// <param name="arrayIndex">Index to start insertion in the array.</param>
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
var node = head.Next[0];
|
||||
while (node != end)
|
||||
var node = this.head.Next[0];
|
||||
while (node != this.end)
|
||||
{
|
||||
array[arrayIndex] = node.Key;
|
||||
arrayIndex++;
|
||||
@@ -174,15 +184,16 @@
|
||||
/// <returns>Array filled with elements from the collection.</returns>
|
||||
public T[] ToArray()
|
||||
{
|
||||
var array = new T[count];
|
||||
var array = new T[this.count];
|
||||
var index = 0;
|
||||
var curNode = head.Next[0];
|
||||
while (curNode != end)
|
||||
var curNode = this.head.Next[0];
|
||||
while (curNode != this.end)
|
||||
{
|
||||
array[index] = curNode.Key;
|
||||
index++;
|
||||
curNode = curNode.Next[0];
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -191,8 +202,8 @@
|
||||
/// <returns></returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
var curNode = head.Next[0];
|
||||
while (curNode != end)
|
||||
var curNode = this.head.Next[0];
|
||||
while (curNode != this.end)
|
||||
{
|
||||
yield return curNode.Key;
|
||||
curNode = curNode.Next[0];
|
||||
@@ -206,11 +217,11 @@
|
||||
}
|
||||
private NodeSet<T> Find(T key)
|
||||
{
|
||||
var curNode = head;
|
||||
var curNode = this.head;
|
||||
|
||||
for (var i = level; i >= 0; i--)
|
||||
for (var i = this.level; i >= 0; i--)
|
||||
{
|
||||
while (curNode.Next[i] != end)
|
||||
while (curNode.Next[i] != this.end)
|
||||
{
|
||||
if (curNode.Next[i].Key.CompareTo(key) > 0)
|
||||
{
|
||||
@@ -220,17 +231,18 @@
|
||||
{
|
||||
return curNode.Next[i];
|
||||
}
|
||||
|
||||
curNode = curNode.Next[i];
|
||||
}
|
||||
}
|
||||
|
||||
curNode = curNode.Next[0];
|
||||
if (curNode != end && curNode.Key.CompareTo(key) == 0)
|
||||
if (curNode != this.end && curNode.Key.CompareTo(key) == 0)
|
||||
{
|
||||
return curNode;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace System.Collections.Generic
|
||||
{
|
||||
namespace System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Treap implementation.
|
||||
/// </summary>
|
||||
@@ -16,10 +16,10 @@
|
||||
public Node<TKey> Left, Right;
|
||||
public Node(TKey key, int priority)
|
||||
{
|
||||
Key = key;
|
||||
Priority = priority;
|
||||
Left = null;
|
||||
Right = null;
|
||||
this.Key = key;
|
||||
this.Priority = priority;
|
||||
this.Left = null;
|
||||
this.Right = null;
|
||||
}
|
||||
}
|
||||
private readonly Random randomGen;
|
||||
@@ -34,7 +34,7 @@
|
||||
{
|
||||
get
|
||||
{
|
||||
return count;
|
||||
return this.count;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
@@ -48,7 +48,7 @@
|
||||
/// </summary>
|
||||
public Treap()
|
||||
{
|
||||
randomGen = new Random();
|
||||
this.randomGen = new Random();
|
||||
}
|
||||
#endregion
|
||||
#region Public Methods
|
||||
@@ -58,8 +58,8 @@
|
||||
/// <param name="value">Value to be added.</param>
|
||||
public void Add(T value)
|
||||
{
|
||||
root = InsertNode(root, value);
|
||||
count++;
|
||||
this.root = this.InsertNode(this.root, value);
|
||||
this.count++;
|
||||
}
|
||||
/// <summary>
|
||||
/// Removes value from treap.
|
||||
@@ -67,8 +67,8 @@
|
||||
/// <param name="value">Value to be removed.</param>
|
||||
public bool Remove(T value)
|
||||
{
|
||||
root = RemoveNode(root, value);
|
||||
count--;
|
||||
this.root = this.RemoveNode(this.root, value);
|
||||
this.count--;
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -76,9 +76,9 @@
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
Clear(root);
|
||||
root = null;
|
||||
count = 0;
|
||||
this.Clear(this.root);
|
||||
this.root = null;
|
||||
this.count = 0;
|
||||
}
|
||||
/// <summary>
|
||||
/// Determines whether the treap contains the specified value.
|
||||
@@ -87,7 +87,7 @@
|
||||
/// <returns></returns>
|
||||
public bool Contains(T value)
|
||||
{
|
||||
return Find(root, value) != null;
|
||||
return this.Find(this.root, value) != null;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the treap structure as an ordered array.
|
||||
@@ -95,11 +95,11 @@
|
||||
/// <returns>Ordered array containing the values stored in the treap.</returns>
|
||||
public T[] ToArray()
|
||||
{
|
||||
if (root != null)
|
||||
if (this.root != null)
|
||||
{
|
||||
var array = new T[count];
|
||||
var array = new T[this.count];
|
||||
var index = 0;
|
||||
ToArray(root, ref array, ref index);
|
||||
this.ToArray(this.root, ref array, ref index);
|
||||
return array;
|
||||
}
|
||||
else
|
||||
@@ -114,7 +114,7 @@
|
||||
/// <param name="arrayIndex">Starting index of the array.</param>
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
ToArray(root, ref array, ref arrayIndex);
|
||||
this.ToArray(this.root, ref array, ref arrayIndex);
|
||||
}
|
||||
/// <summary>
|
||||
/// Enumerator that iterates over the treap. Note that the values are not guaranteed to be sorted.
|
||||
@@ -122,7 +122,7 @@
|
||||
/// <returns>Enumerator that iterates over the treap.</returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return GetEnumerator(root);
|
||||
return this.GetEnumerator(this.root);
|
||||
}
|
||||
#endregion
|
||||
#region Private Methods
|
||||
@@ -130,25 +130,26 @@
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
node = new Node<T>(key, randomGen.Next(0, 100));
|
||||
node = new Node<T>(key, this.randomGen.Next(0, 100));
|
||||
return node;
|
||||
}
|
||||
else if (key.CompareTo(node.Key) <= 0)
|
||||
{
|
||||
node.Left = InsertNode(node.Left, key);
|
||||
node.Left = this.InsertNode(node.Left, key);
|
||||
if (node.Left.Priority > node.Priority)
|
||||
{
|
||||
node = RotateRight(node);
|
||||
node = this.RotateRight(node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
node.Right = InsertNode(node.Right, key);
|
||||
node.Right = this.InsertNode(node.Right, key);
|
||||
if (node.Right.Priority > node.Priority)
|
||||
{
|
||||
node = RotateLeft(node);
|
||||
node = this.RotateLeft(node);
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
private Node<T> RemoveNode(Node<T> node, T key)
|
||||
@@ -157,13 +158,14 @@
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
if (key.CompareTo(node.Key) < 0)
|
||||
{
|
||||
node.Left = RemoveNode(node.Left, key);
|
||||
node.Left = this.RemoveNode(node.Left, key);
|
||||
}
|
||||
else if (key.CompareTo(node.Key) > 0)
|
||||
{
|
||||
node.Right = RemoveNode(node.Right, key);
|
||||
node.Right = this.RemoveNode(node.Right, key);
|
||||
}
|
||||
else if (node.Left == null)
|
||||
{
|
||||
@@ -175,14 +177,15 @@
|
||||
}
|
||||
else if (node.Left.Priority < node.Right.Priority)
|
||||
{
|
||||
node = RotateLeft(node);
|
||||
node.Left = RemoveNode(node.Left, key);
|
||||
node = this.RotateLeft(node);
|
||||
node.Left = this.RemoveNode(node.Left, key);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = RotateRight(node);
|
||||
node.Right = RemoveNode(node.Right, key);
|
||||
node = this.RotateRight(node);
|
||||
node.Right = this.RemoveNode(node.Right, key);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
private Node<T> RotateRight(Node<T> node)
|
||||
@@ -203,12 +206,14 @@
|
||||
{
|
||||
if (node.Left != null)
|
||||
{
|
||||
Clear(node.Left);
|
||||
this.Clear(node.Left);
|
||||
}
|
||||
|
||||
if (node.Right != null)
|
||||
{
|
||||
Clear(node.Right);
|
||||
this.Clear(node.Right);
|
||||
}
|
||||
|
||||
node.Left = node.Right = null;
|
||||
}
|
||||
private Node<T> Find(Node<T> node, T key)
|
||||
@@ -221,20 +226,22 @@
|
||||
{
|
||||
if (node.Key.CompareTo(key) < 0)
|
||||
{
|
||||
var found = Find(node.Left, key);
|
||||
var found = this.Find(node.Left, key);
|
||||
if (found == null)
|
||||
{
|
||||
found = Find(node.Right, key);
|
||||
found = this.Find(node.Right, key);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
else if (node.Key.CompareTo(key) > 0)
|
||||
{
|
||||
var found = Find(node.Right, key);
|
||||
var found = this.Find(node.Right, key);
|
||||
if (found == null)
|
||||
{
|
||||
found = Find(node.Left, key);
|
||||
found = this.Find(node.Left, key);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
else
|
||||
@@ -247,10 +254,10 @@
|
||||
{
|
||||
if (node != null)
|
||||
{
|
||||
ToArray(node.Left, ref array, ref index);
|
||||
this.ToArray(node.Left, ref array, ref index);
|
||||
array[index] = node.Key;
|
||||
index++;
|
||||
ToArray(node.Right, ref array, ref index);
|
||||
this.ToArray(node.Right, ref array, ref index);
|
||||
}
|
||||
}
|
||||
private IEnumerator<T> GetEnumerator(Node<T> currentNode)
|
||||
@@ -265,6 +272,7 @@
|
||||
{
|
||||
queue.Enqueue(currentNode.Left);
|
||||
}
|
||||
|
||||
if (currentNode.Right != null)
|
||||
{
|
||||
queue.Enqueue(currentNode.Right);
|
||||
@@ -277,4 +285,3 @@
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.IO;
|
||||
|
||||
namespace System.Extensions
|
||||
{
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class BytesExtensions
|
||||
{
|
||||
public static byte[] ReadAllBytes(this Stream stream)
|
||||
@@ -12,8 +12,7 @@ namespace System.Extensions
|
||||
}
|
||||
|
||||
var buffer = new byte[256];
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
int read;
|
||||
while ((read = stream.Read(buffer, 0, 256)) > 0)
|
||||
{
|
||||
@@ -23,5 +22,3 @@ namespace System.Extensions
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace System.Extensions
|
||||
{
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class CastExtensions
|
||||
{
|
||||
public static int Floor(this double value)
|
||||
@@ -47,4 +47,3 @@
|
||||
return (int)value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace System.Extensions
|
||||
{
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class LinqExtensions
|
||||
{
|
||||
public static bool None<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
|
||||
@@ -70,6 +70,7 @@ namespace System.Extensions
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
@@ -85,4 +86,3 @@ namespace System.Extensions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Logging;
|
||||
|
||||
namespace System.Extensions
|
||||
{
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class LoggingExtensions
|
||||
{
|
||||
public static ScopedLogger<T> CreateScopedLogger<T>(this ILogger<T> logger, string methodName, string flowIdentifier)
|
||||
@@ -10,4 +10,3 @@ namespace System.Extensions
|
||||
return ScopedLogger<T>.Create(logger, methodName, flowIdentifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace System.Extensions
|
||||
{
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class ObjectExtensions
|
||||
{
|
||||
public static T Deserialize<T>(this string serialized)
|
||||
@@ -56,4 +56,3 @@ namespace System.Extensions
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace System.Extensions
|
||||
{
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class Optional
|
||||
{
|
||||
public static Optional<T> None<T>()
|
||||
@@ -35,7 +35,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
return Value;
|
||||
return this.Value;
|
||||
}
|
||||
}
|
||||
public Optional<T> Do(Action<T> onSome, Action onNone)
|
||||
@@ -58,6 +58,7 @@
|
||||
{
|
||||
onNone.Invoke();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
public Optional<T> DoAny(Action<T> onSome = null, Action onNone = null)
|
||||
@@ -70,6 +71,7 @@
|
||||
{
|
||||
onNone?.Invoke();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
public Optional<V> Switch<V>(Func<T, V> onSome, Func<V> onNone)
|
||||
@@ -189,4 +191,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
namespace System.Extensions
|
||||
{
|
||||
namespace System.Extensions;
|
||||
|
||||
public class Result<TSuccess, TFailure>
|
||||
{
|
||||
private readonly object value;
|
||||
|
||||
public Result(TSuccess successValue)
|
||||
{
|
||||
value = successValue;
|
||||
this.value = successValue;
|
||||
}
|
||||
public Result(TFailure failureValue)
|
||||
{
|
||||
value = failureValue;
|
||||
this.value = failureValue;
|
||||
}
|
||||
|
||||
public bool TryExtractSuccess(out TSuccess successValue)
|
||||
{
|
||||
|
||||
if (value is TSuccess success)
|
||||
if (this.value is TSuccess success)
|
||||
{
|
||||
successValue = success;
|
||||
return true;
|
||||
@@ -30,7 +30,7 @@
|
||||
public bool TryExtractFailure(out TFailure failureValue)
|
||||
{
|
||||
|
||||
if (value is TFailure failure)
|
||||
if (this.value is TFailure failure)
|
||||
{
|
||||
failureValue = failure;
|
||||
return true;
|
||||
@@ -53,26 +53,28 @@
|
||||
throw new ArgumentNullException(nameof(onFailure));
|
||||
}
|
||||
|
||||
if (value is TSuccess)
|
||||
if (this.value is TSuccess)
|
||||
{
|
||||
onSuccess.Invoke();
|
||||
}
|
||||
else if (value is TFailure)
|
||||
else if (this.value is TFailure)
|
||||
{
|
||||
onFailure.Invoke();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
public Result<TSuccess, TFailure> DoAny(Action onSuccess = null, Action onFailure = null)
|
||||
{
|
||||
if (value is TSuccess)
|
||||
if (this.value is TSuccess)
|
||||
{
|
||||
onSuccess?.Invoke();
|
||||
}
|
||||
else if (value is TFailure)
|
||||
else if (this.value is TFailure)
|
||||
{
|
||||
onFailure?.Invoke();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
public Result<TSuccess, TFailure> Do(Action<TSuccess> onSuccess, Action<TFailure> onFailure)
|
||||
@@ -87,26 +89,28 @@
|
||||
throw new ArgumentNullException(nameof(onFailure));
|
||||
}
|
||||
|
||||
if (value is TSuccess success)
|
||||
if (this.value is TSuccess success)
|
||||
{
|
||||
onSuccess.Invoke(success);
|
||||
}
|
||||
else if (value is TFailure failure)
|
||||
else if (this.value is TFailure failure)
|
||||
{
|
||||
onFailure.Invoke(failure);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
public Result<TSuccess, TFailure> DoAny(Action<TSuccess> onSuccess = null, Action<TFailure> onFailure = null)
|
||||
{
|
||||
if (value is TSuccess success)
|
||||
if (this.value is TSuccess success)
|
||||
{
|
||||
onSuccess?.Invoke(success);
|
||||
}
|
||||
else if (value is TFailure failure)
|
||||
else if (this.value is TFailure failure)
|
||||
{
|
||||
onFailure?.Invoke(failure);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
public T Switch<T>(Func<TSuccess, T> onSuccess, Func<TFailure, T> onFailure)
|
||||
@@ -121,27 +125,29 @@
|
||||
throw new ArgumentNullException(nameof(onFailure));
|
||||
}
|
||||
|
||||
if (value is TSuccess success)
|
||||
if (this.value is TSuccess success)
|
||||
{
|
||||
return onSuccess.Invoke(success);
|
||||
}
|
||||
else if (value is TFailure failure)
|
||||
else if (this.value is TFailure failure)
|
||||
{
|
||||
return onFailure.Invoke(failure);
|
||||
}
|
||||
throw new InvalidOperationException($"{nameof(value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to {typeof(T)}");
|
||||
|
||||
throw new InvalidOperationException($"{nameof(this.value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to {typeof(T)}");
|
||||
}
|
||||
public T SwitchAny<T>(Func<TSuccess, T> onSuccess = null, Func<TFailure, T> onFailure = null)
|
||||
{
|
||||
if (value is TSuccess success)
|
||||
if (this.value is TSuccess success)
|
||||
{
|
||||
return onSuccess is null ? default : onSuccess.Invoke(success);
|
||||
}
|
||||
else if (value is TFailure failure)
|
||||
else if (this.value is TFailure failure)
|
||||
{
|
||||
return onFailure is null ? default : onFailure.Invoke(failure);
|
||||
}
|
||||
throw new InvalidOperationException($"{nameof(value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to {typeof(T)}");
|
||||
|
||||
throw new InvalidOperationException($"{nameof(this.value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to {typeof(T)}");
|
||||
}
|
||||
public Result<V, K> Switch<V, K>(Func<TSuccess, V> onSuccess, Func<TFailure, K> onFailure)
|
||||
{
|
||||
@@ -155,33 +161,35 @@
|
||||
throw new ArgumentNullException(nameof(onFailure));
|
||||
}
|
||||
|
||||
if (value is TSuccess success)
|
||||
if (this.value is TSuccess success)
|
||||
{
|
||||
return Result<V, K>.Success(onSuccess.Invoke(success));
|
||||
}
|
||||
else if (value is TFailure failure)
|
||||
else if (this.value is TFailure failure)
|
||||
{
|
||||
return Result<V, K>.Failure(onFailure.Invoke(failure));
|
||||
}
|
||||
throw new InvalidOperationException($"{nameof(value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to Result of type {typeof(V)} or {typeof(K)}");
|
||||
|
||||
throw new InvalidOperationException($"{nameof(this.value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to Result of type {typeof(V)} or {typeof(K)}");
|
||||
}
|
||||
public Result<V, K> SwitchAny<V, K>(Func<TSuccess, V> onSuccess, Func<TFailure, K> onFailure)
|
||||
{
|
||||
if (value is TSuccess success)
|
||||
if (this.value is TSuccess success)
|
||||
{
|
||||
return Result<V, K>.Success(onSuccess is null ? default : onSuccess.Invoke(success));
|
||||
}
|
||||
else if (value is TFailure failure)
|
||||
else if (this.value is TFailure failure)
|
||||
{
|
||||
return Result<V, K>.Failure(onFailure is null ? default : onFailure.Invoke(failure));
|
||||
}
|
||||
throw new InvalidOperationException($"{nameof(value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to Result of type {typeof(V)} or {typeof(K)}");
|
||||
|
||||
throw new InvalidOperationException($"{nameof(this.value)} must be of type {typeof(TSuccess)} or {typeof(TFailure)} in order to switch to Result of type {typeof(V)} or {typeof(K)}");
|
||||
}
|
||||
public Optional<TSuccess> ToOptional()
|
||||
{
|
||||
if (value is TSuccess)
|
||||
if (this.value is TSuccess)
|
||||
{
|
||||
return Optional.FromValue(value.Cast<TSuccess>());
|
||||
return Optional.FromValue(this.value.Cast<TSuccess>());
|
||||
}
|
||||
|
||||
return Optional.None<TSuccess>();
|
||||
@@ -206,4 +214,3 @@
|
||||
return new Result<TSuccess, TFailure>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Extensions
|
||||
{
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class StreamExtensions
|
||||
{
|
||||
public static void DoWhileReading(this Stream stream, Action<int, byte[]> action, int bufferLength = 256)
|
||||
@@ -82,4 +82,3 @@ namespace System.Extensions
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Text;
|
||||
|
||||
namespace System.Extensions
|
||||
{
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class StringExtensions
|
||||
{
|
||||
public static bool IsNullOrEmpty(this string s)
|
||||
@@ -24,4 +24,3 @@ namespace System.Extensions
|
||||
return Encoding.UTF8.GetString(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Extensions
|
||||
{
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class TaskExtensions
|
||||
{
|
||||
/// <summary>
|
||||
@@ -136,41 +136,43 @@ namespace System.Extensions
|
||||
|
||||
public override void Post(SendOrPostCallback d, object state)
|
||||
{
|
||||
lock (items)
|
||||
lock (this.items)
|
||||
{
|
||||
items.Enqueue(Tuple.Create(d, state));
|
||||
this.items.Enqueue(Tuple.Create(d, state));
|
||||
}
|
||||
workItemsWaiting.Set();
|
||||
|
||||
this.workItemsWaiting.Set();
|
||||
}
|
||||
|
||||
public void EndMessageLoop()
|
||||
{
|
||||
Post(_ => done = true, null);
|
||||
this.Post(_ => this.done = true, null);
|
||||
}
|
||||
|
||||
public void BeginMessageLoop()
|
||||
{
|
||||
while (!done)
|
||||
while (!this.done)
|
||||
{
|
||||
Tuple<SendOrPostCallback, object> task = null;
|
||||
lock (items)
|
||||
lock (this.items)
|
||||
{
|
||||
if (items.Count > 0)
|
||||
if (this.items.Count > 0)
|
||||
{
|
||||
task = items.Dequeue();
|
||||
task = this.items.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
if (task != null)
|
||||
{
|
||||
task.Item1(task.Item2);
|
||||
if (InnerException != null) // the method threw an exeption
|
||||
if (this.InnerException != null) // the method threw an exeption
|
||||
{
|
||||
throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
|
||||
throw new AggregateException("AsyncHelpers.Run method threw an exception.", this.InnerException);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
workItemsWaiting.WaitOne();
|
||||
this.workItemsWaiting.WaitOne();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,4 +183,3 @@ namespace System.Extensions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Extensions
|
||||
{
|
||||
namespace System.Extensions;
|
||||
|
||||
public static class Try
|
||||
{
|
||||
public static Try<TResult> Action<TResult>(Func<TResult> act)
|
||||
@@ -32,7 +32,7 @@ namespace System.Extensions
|
||||
{
|
||||
try
|
||||
{
|
||||
return action();
|
||||
return this.action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -40,6 +40,7 @@ namespace System.Extensions
|
||||
{
|
||||
return catchAction(ex);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -61,6 +62,7 @@ namespace System.Extensions
|
||||
{
|
||||
return catchAction(ex);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
@@ -69,4 +71,3 @@ namespace System.Extensions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Http
|
||||
{
|
||||
namespace System.Net.Http;
|
||||
|
||||
public sealed class HttpClient<Tscope> : IHttpClient<Tscope>, IDisposable
|
||||
{
|
||||
private readonly HttpClient httpClient;
|
||||
@@ -214,4 +213,3 @@ namespace System.Http
|
||||
this.eventEmitted?.Invoke(this, new HttpClientEventMessage(this.scope, method, url));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace System.Http
|
||||
{
|
||||
namespace System.Net.Http;
|
||||
|
||||
public sealed class HttpClientEventMessage
|
||||
{
|
||||
public Type Scope { get; }
|
||||
@@ -13,4 +13,3 @@
|
||||
this.Url = url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Http
|
||||
{
|
||||
namespace System.Net.Http;
|
||||
|
||||
public interface IHttpClient<TScope>
|
||||
{
|
||||
event EventHandler<HttpClientEventMessage> EventEmitted;
|
||||
@@ -46,4 +45,3 @@ namespace System.Http
|
||||
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken);
|
||||
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Extensions;
|
||||
|
||||
namespace System.Logging
|
||||
{
|
||||
namespace System.Logging;
|
||||
|
||||
public struct ScopedLogger<T>
|
||||
{
|
||||
private readonly ILogger<T> logger;
|
||||
@@ -71,7 +71,6 @@ namespace System.Logging
|
||||
|
||||
public static ScopedLogger<T> Create(ILogger<T> logger, string scope, string flowId)
|
||||
{
|
||||
return new ScopedLogger<T>(logger, scope.ThrowIfNull(nameof(scope)), flowId.ThrowIfNull(nameof(flowId)));
|
||||
}
|
||||
return new ScopedLogger<T>(logger, scope.ThrowIfNull(nameof(scope)), flowId);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
namespace System.Structures.BitStructures
|
||||
{
|
||||
namespace System.Structures.BitStructures;
|
||||
|
||||
public struct Int32BitStruct : IEquatable<Int32BitStruct>
|
||||
{
|
||||
public Int32BitStruct(uint value) => this.Value = value;
|
||||
@@ -172,4 +172,3 @@
|
||||
return (this.Value).GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
|
||||
namespace System.Structures.BitStructures
|
||||
{
|
||||
namespace System.Structures.BitStructures;
|
||||
|
||||
public struct Int64BitStruct : IEquatable<Int64BitStruct>
|
||||
{
|
||||
public Int64BitStruct(uint low, uint high)
|
||||
@@ -202,4 +202,3 @@ namespace System.Structures.BitStructures
|
||||
return this.Value.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<RootNamespace>System</RootNamespace>
|
||||
<Version>1.4</Version>
|
||||
<Version>1.5</Version>
|
||||
<Authors>Alexandru Macocian</Authors>
|
||||
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
|
||||
<Description>Extensions for the System namespace</Description>
|
||||
@@ -18,10 +18,11 @@
|
||||
<Pack>True</Pack>
|
||||
<PackagePath></PackagePath>
|
||||
</None>
|
||||
<None Include="..\.editorconfig" Link=".editorconfig" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System;
|
||||
|
||||
/// <summary>
|
||||
/// Async implementation of <see cref="Lazy{T}"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Credits: https://devblogs.microsoft.com/pfxteam/asynclazyt/
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">Type of value to be returned.</typeparam>
|
||||
public sealed class AsyncLazy<T> : Lazy<Task<T>>
|
||||
{
|
||||
public TaskAwaiter<T> GetAwaiter() => this.Value.GetAwaiter();
|
||||
|
||||
public AsyncLazy(Func<T> valueFactory)
|
||||
: base(() => Task.Factory.StartNew(valueFactory))
|
||||
{
|
||||
}
|
||||
|
||||
public AsyncLazy(Func<Task<T>> taskFactory)
|
||||
: base(() => Task.Factory.StartNew(() => taskFactory()).Unwrap())
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Threading
|
||||
{
|
||||
namespace System.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// Threadpool implementation that uses a priority queue as the queue for the tasks to execute.
|
||||
/// Features both an automated algorithm to calibrate the number of active threads and a Constructor for constructing
|
||||
@@ -42,6 +42,7 @@ namespace System.Threading
|
||||
priority1 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (other.TaskPriority)
|
||||
{
|
||||
case TaskPriority.Highest:
|
||||
@@ -60,6 +61,7 @@ namespace System.Threading
|
||||
priority2 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (priority1 == priority2)
|
||||
{
|
||||
return 0;
|
||||
@@ -111,7 +113,6 @@ namespace System.Threading
|
||||
private volatile PriorityQueue<QueueEntry> tasks;
|
||||
private Thread observer;
|
||||
private CancellationTokenSource observerCancellationTokenSource = new CancellationTokenSource();
|
||||
private int maxThreads;
|
||||
private readonly object tasksLock = new object();
|
||||
private struct WorkerThread
|
||||
{
|
||||
@@ -152,17 +153,7 @@ namespace System.Threading
|
||||
/// <summary>
|
||||
/// Maximum amount of threads that the pool can utilize
|
||||
/// </summary>
|
||||
public int MaxThreads
|
||||
{
|
||||
set
|
||||
{
|
||||
maxThreads = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
return maxThreads;
|
||||
}
|
||||
}
|
||||
public int MaxThreads { set; get; }
|
||||
#endregion
|
||||
#region Constructors
|
||||
/// <summary>
|
||||
@@ -171,19 +162,20 @@ namespace System.Threading
|
||||
/// </summary>
|
||||
public PriorityThreadPool()
|
||||
{
|
||||
threadpool = new List<WorkerThread>();
|
||||
tasks = new PriorityQueue<QueueEntry>();
|
||||
maxThreads = System.Environment.ProcessorCount;
|
||||
for (var i = 0; i < maxThreads; i++)
|
||||
this.threadpool = new List<WorkerThread>();
|
||||
this.tasks = new PriorityQueue<QueueEntry>();
|
||||
this.MaxThreads = System.Environment.ProcessorCount;
|
||||
for (var i = 0; i < this.MaxThreads; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread();
|
||||
}
|
||||
observer = new Thread(() => ObserverLoop())
|
||||
|
||||
this.observer = new Thread(() => this.ObserverLoop())
|
||||
{
|
||||
Name = "ThreadPool ObserverThread",
|
||||
Priority = ThreadPriority.BelowNormal
|
||||
};
|
||||
observer.Start();
|
||||
this.observer.Start();
|
||||
}
|
||||
/// <summary>
|
||||
/// Constructor that initializes a threadpool with a number of threads, all of the same priority.
|
||||
@@ -191,17 +183,18 @@ namespace System.Threading
|
||||
/// <param name="maxThreads">Maximum number of threads</param>
|
||||
public PriorityThreadPool(int maxThreads)
|
||||
{
|
||||
threadpool = new List<WorkerThread>();
|
||||
tasks = new PriorityQueue<QueueEntry>();
|
||||
this.maxThreads = Math.Max(maxThreads, 1);
|
||||
this.threadpool = new List<WorkerThread>();
|
||||
this.tasks = new PriorityQueue<QueueEntry>();
|
||||
this.MaxThreads = Math.Max(maxThreads, 1);
|
||||
for (var i = 0; i < maxThreads; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread();
|
||||
}
|
||||
observer = new Thread(() => ObserverLoop());
|
||||
observer.Name = "ThreadPool ObserverThread";
|
||||
observer.Priority = ThreadPriority.BelowNormal;
|
||||
observer.Start();
|
||||
|
||||
this.observer = new Thread(() => this.ObserverLoop());
|
||||
this.observer.Name = "ThreadPool ObserverThread";
|
||||
this.observer.Priority = ThreadPriority.BelowNormal;
|
||||
this.observer.Start();
|
||||
}
|
||||
/// <summary>
|
||||
/// Constructor for a manually-configured threadpool that runs a specified number of threads.
|
||||
@@ -214,24 +207,28 @@ namespace System.Threading
|
||||
/// <param name="highest">Number of threads with Highest priority.</param>
|
||||
public PriorityThreadPool(int lowest, int belowNormal, int normal, int aboveNormal, int highest)
|
||||
{
|
||||
threadpool = new List<WorkerThread>();
|
||||
tasks = new PriorityQueue<QueueEntry>();
|
||||
this.threadpool = new List<WorkerThread>();
|
||||
this.tasks = new PriorityQueue<QueueEntry>();
|
||||
for (var i = 0; i < lowest; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread(ThreadPriority.Lowest);
|
||||
}
|
||||
|
||||
for (var i = 0; i < belowNormal; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread(ThreadPriority.BelowNormal);
|
||||
}
|
||||
|
||||
for (var i = 0; i < normal; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread(ThreadPriority.Normal);
|
||||
}
|
||||
|
||||
for (var i = 0; i < aboveNormal; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread(ThreadPriority.AboveNormal);
|
||||
}
|
||||
|
||||
for (var i = 0; i < highest; i++)
|
||||
{
|
||||
this.CreateAndStartWorkerThread(ThreadPriority.Highest);
|
||||
@@ -247,13 +244,13 @@ namespace System.Threading
|
||||
/// <param name="taskPriority">Priority of task. Affects its position into the queue.</param>
|
||||
public void QueueUserWorkItem(WaitCallback waitCallback, object callbackState, TaskPriority taskPriority)
|
||||
{
|
||||
while (!Monitor.TryEnter(tasksLock))
|
||||
while (!Monitor.TryEnter(this.tasksLock))
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
tasks.Enqueue(new QueueEntry(taskPriority, waitCallback, callbackState));
|
||||
Monitor.Exit(tasksLock);
|
||||
this.tasks.Enqueue(new QueueEntry(taskPriority, waitCallback, callbackState));
|
||||
Monitor.Exit(this.tasksLock);
|
||||
}
|
||||
/// <summary>
|
||||
/// Add a work item into the queue.
|
||||
@@ -262,30 +259,30 @@ namespace System.Threading
|
||||
/// <param name="callbackState">State used as parameter during invoke.</param>
|
||||
public void QueueUserWorkItem(WaitCallback waitCallback, object callbackState)
|
||||
{
|
||||
QueueUserWorkItem(waitCallback, callbackState, TaskPriority.Normal);
|
||||
this.QueueUserWorkItem(waitCallback, callbackState, TaskPriority.Normal);
|
||||
}
|
||||
#endregion
|
||||
#region Private Methods
|
||||
private void CreateAndStartWorkerThread(ThreadPriority threadPriority)
|
||||
{
|
||||
var worker = new WorkerThread();
|
||||
worker.Thread = new Thread(() => ThreadMainLoop(ref worker));
|
||||
worker.Thread = new Thread(() => this.ThreadMainLoop(ref worker));
|
||||
worker.Thread.Name = "ThreadPool WorkerThread";
|
||||
worker.Thread.Priority = threadPriority;
|
||||
worker.Running = true;
|
||||
worker.CancellationTokenSource = new CancellationTokenSource();
|
||||
worker.Thread.Start();
|
||||
threadpool.Add(worker);
|
||||
this.threadpool.Add(worker);
|
||||
}
|
||||
private void CreateAndStartWorkerThread()
|
||||
{
|
||||
var worker = new WorkerThread();
|
||||
worker.Thread = new Thread(() => ThreadMainLoop(ref worker));
|
||||
worker.Thread = new Thread(() => this.ThreadMainLoop(ref worker));
|
||||
worker.Thread.Name = "ThreadPool WorkerThread";
|
||||
worker.Running = true;
|
||||
worker.CancellationTokenSource = new CancellationTokenSource();
|
||||
worker.Thread.Start();
|
||||
threadpool.Add(worker);
|
||||
this.threadpool.Add(worker);
|
||||
}
|
||||
/// <summary>
|
||||
/// Main loop that a thread from the pool is running.
|
||||
@@ -303,7 +300,7 @@ namespace System.Threading
|
||||
}
|
||||
|
||||
//Check if there are tasks
|
||||
if (tasks.Count > 0)
|
||||
if (this.tasks.Count > 0)
|
||||
{
|
||||
//If there are tasks, acquire a lock onto the list
|
||||
//and try to dequeue the highest priority task.
|
||||
@@ -311,22 +308,24 @@ namespace System.Threading
|
||||
|
||||
thisWorkerThread.Working = true;
|
||||
QueueEntry task = null;
|
||||
while (!Monitor.TryEnter(tasksLock))
|
||||
while (!Monitor.TryEnter(this.tasksLock))
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
if (tasks.Count > 0)
|
||||
if (this.tasks.Count > 0)
|
||||
{
|
||||
task = tasks.Dequeue();
|
||||
task = this.tasks.Dequeue();
|
||||
}
|
||||
Monitor.Exit(tasksLock);
|
||||
|
||||
Monitor.Exit(this.tasksLock);
|
||||
if (task != null)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.Name + " - Running task!");
|
||||
var waitCallback = task.WaitCallback;
|
||||
waitCallback.Invoke(task.Object);
|
||||
}
|
||||
|
||||
thisWorkerThread.Working = false;
|
||||
}
|
||||
}
|
||||
@@ -346,7 +345,7 @@ namespace System.Threading
|
||||
//If counter is under -10, it will try to remove a thread from the threadpool, unless the threadpool has reached less than
|
||||
//max size / 4.
|
||||
|
||||
if (observerCancellationTokenSource.Token.IsCancellationRequested)
|
||||
if (this.observerCancellationTokenSource.Token.IsCancellationRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -368,13 +367,14 @@ namespace System.Threading
|
||||
{
|
||||
statistics.Initialized = true;
|
||||
}
|
||||
|
||||
statistics.LastUpdate = DateTime.Now;
|
||||
|
||||
Thread.Sleep(100);
|
||||
|
||||
|
||||
//This part of code adjusts the performance counter. Ideally, the value should be 0.
|
||||
if (tasks.Count > 0)
|
||||
if (this.tasks.Count > 0)
|
||||
{
|
||||
statistics.PerformanceCounter++;
|
||||
if (statistics.PerformanceCounter > 5)
|
||||
@@ -392,22 +392,22 @@ namespace System.Threading
|
||||
}
|
||||
|
||||
//This part of code adjusts thread priorities based on the current performance of the threadpool
|
||||
if (tasks.Count > 0)
|
||||
if (this.tasks.Count > 0)
|
||||
{
|
||||
//If there are tasks pending, find a thread with priority under Normal and upgrade its priority.
|
||||
var t = FindThreadWithLowPriority();
|
||||
var t = this.FindThreadWithLowPriority();
|
||||
if (t != null)
|
||||
{
|
||||
UpgradeThreadPriority(t);
|
||||
this.UpgradeThreadPriority(t);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//If there are no tasks pending, find a thread with priority above Lowest and downgrade its priority.
|
||||
var t = FindThreadWithAcceptablePriority();
|
||||
var t = this.FindThreadWithAcceptablePriority();
|
||||
if (t != null)
|
||||
{
|
||||
DowngradeThreadPriority(t);
|
||||
this.DowngradeThreadPriority(t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +415,7 @@ namespace System.Threading
|
||||
//This part of code modifies the number of active threads based on the current performance of the threadpool
|
||||
if (statistics.PerformanceCounter >= 5)
|
||||
{
|
||||
if (threadpool.Count < this.maxThreads)
|
||||
if (this.threadpool.Count < this.MaxThreads)
|
||||
{
|
||||
//Add a thread to the threadpool.
|
||||
//Reset counter to 0.
|
||||
@@ -425,13 +425,13 @@ namespace System.Threading
|
||||
}
|
||||
else if (statistics.PerformanceCounter <= -10)
|
||||
{
|
||||
if (threadpool.Count > maxThreads / 4)
|
||||
if (this.threadpool.Count > this.MaxThreads / 4)
|
||||
{
|
||||
//Remove the last thread in the threadpool.
|
||||
//If thread is currently working, notify it to close.
|
||||
//Else, abort the thread.
|
||||
//Reset counter to 0.
|
||||
var worker = threadpool[threadpool.Count - 1];
|
||||
var worker = this.threadpool[this.threadpool.Count - 1];
|
||||
if (worker.Working)
|
||||
{
|
||||
worker.Running = false;
|
||||
@@ -440,7 +440,8 @@ namespace System.Threading
|
||||
{
|
||||
worker.CancellationTokenSource.Cancel();
|
||||
}
|
||||
threadpool.RemoveAt(threadpool.Count - 1);
|
||||
|
||||
this.threadpool.RemoveAt(this.threadpool.Count - 1);
|
||||
statistics.PerformanceCounter = 0;
|
||||
}
|
||||
}
|
||||
@@ -452,13 +453,14 @@ namespace System.Threading
|
||||
/// <returns>Thread with low priority.</returns>
|
||||
private Thread FindThreadWithLowPriority()
|
||||
{
|
||||
foreach (var t in threadpool)
|
||||
foreach (var t in this.threadpool)
|
||||
{
|
||||
if (t.Thread.Priority == ThreadPriority.Lowest || t.Thread.Priority == ThreadPriority.BelowNormal)
|
||||
{
|
||||
return t.Thread;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -467,13 +469,14 @@ namespace System.Threading
|
||||
/// <returns>Thread with BelowNormal or Normal priority.</returns>
|
||||
private Thread FindThreadWithAcceptablePriority()
|
||||
{
|
||||
foreach (var t in threadpool)
|
||||
foreach (var t in this.threadpool)
|
||||
{
|
||||
if (t.Thread.Priority == ThreadPriority.Normal || t.Thread.Priority == ThreadPriority.BelowNormal)
|
||||
{
|
||||
return t.Thread;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
/// <summary>
|
||||
@@ -546,14 +549,17 @@ namespace System.Threading
|
||||
this.observerCancellationTokenSource.Cancel();
|
||||
this.observer.Join();
|
||||
}
|
||||
foreach (var worker in threadpool)
|
||||
|
||||
foreach (var worker in this.threadpool)
|
||||
{
|
||||
worker.CancellationTokenSource.Cancel();
|
||||
worker.Thread.Join();
|
||||
}
|
||||
|
||||
this.threadpool.Clear();
|
||||
this.tasks.Clear();
|
||||
}
|
||||
|
||||
this.threadpool = null;
|
||||
this.tasks = null;
|
||||
this.observer = null;
|
||||
@@ -565,8 +571,7 @@ namespace System.Threading
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
this.Dispose(true);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ using System.Collections.Generic;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.IO;
|
||||
|
||||
namespace System.Collections.Tests
|
||||
{
|
||||
namespace System.Collections.Tests;
|
||||
|
||||
[TestClass()]
|
||||
public class AVLTreeTests
|
||||
{
|
||||
@@ -12,7 +12,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void AVLTreeTest()
|
||||
{
|
||||
avlTree = new AVLTree<int>();
|
||||
this.avlTree = new AVLTree<int>();
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
@@ -22,14 +22,15 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i * 20 - (50 + i));
|
||||
this.avlTree.Add(i * 20 - (50 + i));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Assert.Fail(e.Message + "\n" + e.StackTrace);
|
||||
}
|
||||
if (avlTree.Count != 100)
|
||||
|
||||
if (this.avlTree.Count != 100)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -40,10 +41,10 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
this.avlTree.Add(i);
|
||||
}
|
||||
|
||||
if (!avlTree.Contains(50))
|
||||
if (!this.avlTree.Contains(50))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -54,12 +55,12 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
this.avlTree.Add(i);
|
||||
}
|
||||
|
||||
avlTree.Remove(50);
|
||||
this.avlTree.Remove(50);
|
||||
|
||||
if (avlTree.Contains(50))
|
||||
if (this.avlTree.Contains(50))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -70,10 +71,11 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
this.avlTree.Add(i);
|
||||
}
|
||||
avlTree.Clear();
|
||||
if(avlTree.Count > 0)
|
||||
|
||||
this.avlTree.Clear();
|
||||
if(this.avlTree.Count > 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -84,11 +86,11 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
this.avlTree.Add(i);
|
||||
}
|
||||
|
||||
var array = new int[100];
|
||||
avlTree.CopyTo(array, 0);
|
||||
this.avlTree.CopyTo(array, 0);
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
@@ -96,16 +98,17 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
this.avlTree.Add(i);
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
foreach(var value in avlTree)
|
||||
foreach(var value in this.avlTree)
|
||||
{
|
||||
count++;
|
||||
System.Diagnostics.Debug.WriteLine(value);
|
||||
}
|
||||
|
||||
if(count != avlTree.Count)
|
||||
if(count != this.avlTree.Count)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -116,10 +119,10 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
this.avlTree.Add(i);
|
||||
}
|
||||
|
||||
var array = avlTree.ToArray();
|
||||
_ = this.avlTree.ToArray();
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
@@ -128,17 +131,18 @@ namespace System.Collections.Tests
|
||||
var avlTree2 = new AVLTree<int>();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
avlTree.Add(i);
|
||||
this.avlTree.Add(i);
|
||||
}
|
||||
|
||||
var serializer = new BinaryFormatter();
|
||||
var s = string.Empty;
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
serializer.Serialize(stream, avlTree);
|
||||
serializer.Serialize(stream, this.avlTree);
|
||||
stream.Position = 0;
|
||||
avlTree2 = (AVLTree<int>)serializer.Deserialize(stream);
|
||||
}
|
||||
var avlTreeEnum = avlTree.GetEnumerator();
|
||||
|
||||
var avlTreeEnum = this.avlTree.GetEnumerator();
|
||||
var avlTree2Enum = avlTree2.GetEnumerator();
|
||||
|
||||
for(var i = 0; i < 100; i++)
|
||||
@@ -147,9 +151,9 @@ namespace System.Collections.Tests
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
avlTreeEnum.MoveNext();
|
||||
avlTree2Enum.MoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ using System.Collections.Generic;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.IO;
|
||||
|
||||
namespace System.Collections.Tests
|
||||
{
|
||||
namespace System.Collections.Tests;
|
||||
|
||||
[TestClass()]
|
||||
public class BinaryHeapTests
|
||||
{
|
||||
@@ -12,14 +12,14 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void BinaryHeapTest()
|
||||
{
|
||||
binaryHeap = new BinaryHeap<int>();
|
||||
this.binaryHeap = new BinaryHeap<int>();
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void BinaryHeapTest1()
|
||||
{
|
||||
binaryHeap = new BinaryHeap<int>(100);
|
||||
if (binaryHeap.Count != 0 && binaryHeap.Capacity != 100)
|
||||
this.binaryHeap = new BinaryHeap<int>(100);
|
||||
if (this.binaryHeap.Count != 0 && this.binaryHeap.Capacity != 100)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -33,14 +33,15 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
binaryHeap.Add(i * 20 - (50 + i));
|
||||
this.binaryHeap.Add(i * 20 - (50 + i));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Assert.Fail(e.Message + "\n" + e.StackTrace);
|
||||
}
|
||||
if (binaryHeap.Count != 100)
|
||||
|
||||
if (this.binaryHeap.Count != 100)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -52,14 +53,15 @@ namespace System.Collections.Tests
|
||||
{
|
||||
try
|
||||
{
|
||||
var tries = binaryHeap.Count;
|
||||
while (binaryHeap.Count > 0)
|
||||
var tries = this.binaryHeap.Count;
|
||||
while (this.binaryHeap.Count > 0)
|
||||
{
|
||||
if (tries == 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
System.Diagnostics.Debug.WriteLine(binaryHeap.Remove());
|
||||
|
||||
System.Diagnostics.Debug.WriteLine(this.binaryHeap.Remove());
|
||||
tries--;
|
||||
}
|
||||
}
|
||||
@@ -74,9 +76,10 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
binaryHeap.Add(i);
|
||||
this.binaryHeap.Add(i);
|
||||
}
|
||||
if (binaryHeap.Min != 0 || binaryHeap.Max != 999)
|
||||
|
||||
if (this.binaryHeap.Min != 0 || this.binaryHeap.Max != 999)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -87,10 +90,11 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
binaryHeap.Add(i);
|
||||
this.binaryHeap.Add(i);
|
||||
}
|
||||
binaryHeap.Clear();
|
||||
if (binaryHeap.Count > 0 || binaryHeap.Capacity != 160)
|
||||
|
||||
this.binaryHeap.Clear();
|
||||
if (this.binaryHeap.Count > 0 || this.binaryHeap.Capacity != 160)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -101,20 +105,23 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 100; i < 200; i++)
|
||||
{
|
||||
binaryHeap.Add(i);
|
||||
this.binaryHeap.Add(i);
|
||||
}
|
||||
binaryHeap.Clear(false);
|
||||
var array = binaryHeap.ToArray();
|
||||
if (binaryHeap.Count > 0 || binaryHeap.Capacity == 10)
|
||||
|
||||
this.binaryHeap.Clear(false);
|
||||
var array = this.binaryHeap.ToArray();
|
||||
if (this.binaryHeap.Count > 0 || this.binaryHeap.Capacity == 10)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
if (array.Length != 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
binaryHeap.Clear(true);
|
||||
if (binaryHeap.Capacity != 10 || binaryHeap.Count != 0)
|
||||
|
||||
this.binaryHeap.Clear(true);
|
||||
if (this.binaryHeap.Capacity != 10 || this.binaryHeap.Count != 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -123,8 +130,8 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ContainsTest()
|
||||
{
|
||||
binaryHeap.Add(100);
|
||||
if (!binaryHeap.Contains(100))
|
||||
this.binaryHeap.Add(100);
|
||||
if (!this.binaryHeap.Contains(100))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -135,13 +142,15 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for(var i = 0; i < 1000; i++)
|
||||
{
|
||||
binaryHeap.Add(i);
|
||||
this.binaryHeap.Add(i);
|
||||
}
|
||||
var array = binaryHeap.ToArray();
|
||||
if(array.Length != binaryHeap.Count)
|
||||
|
||||
var array = this.binaryHeap.ToArray();
|
||||
if(array.Length != this.binaryHeap.Count)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
if(array[0] != 0 && array[999] != 999)
|
||||
{
|
||||
Assert.Fail();
|
||||
@@ -153,16 +162,17 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
binaryHeap.Add(i);
|
||||
this.binaryHeap.Add(i);
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
foreach(var value in binaryHeap)
|
||||
foreach(var value in this.binaryHeap)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(value);
|
||||
count++;
|
||||
}
|
||||
|
||||
if(count == binaryHeap.Count)
|
||||
if(count == this.binaryHeap.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -176,16 +186,17 @@ namespace System.Collections.Tests
|
||||
var binaryHeap2 = new BinaryHeap<int>();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
binaryHeap.Add(i);
|
||||
this.binaryHeap.Add(i);
|
||||
}
|
||||
|
||||
var serializer = new BinaryFormatter();
|
||||
var s = string.Empty;
|
||||
using (var stream = new MemoryStream()) {
|
||||
serializer.Serialize(stream, binaryHeap);
|
||||
serializer.Serialize(stream, this.binaryHeap);
|
||||
stream.Position = 0;
|
||||
binaryHeap2 = (BinaryHeap<int>)serializer.Deserialize(stream);
|
||||
}
|
||||
var binaryHeapEnum = binaryHeap.GetEnumerator();
|
||||
|
||||
var binaryHeapEnum = this.binaryHeap.GetEnumerator();
|
||||
var binaryHeapEnum2 = binaryHeap2.GetEnumerator();
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
@@ -194,9 +205,9 @@ namespace System.Collections.Tests
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
binaryHeapEnum.MoveNext();
|
||||
binaryHeapEnum2.MoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ using System.Collections.Generic;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.IO;
|
||||
|
||||
namespace System.Collections.Tests
|
||||
{
|
||||
namespace System.Collections.Tests;
|
||||
|
||||
[TestClass()]
|
||||
public class FibonacciHeapTests
|
||||
{
|
||||
@@ -14,15 +14,15 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
this.fibonacciHeap.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void FibonacciHeapTest()
|
||||
{
|
||||
fibonacciHeap = new FibonacciHeap<int>();
|
||||
if(fibonacciHeap.Count != 0)
|
||||
this.fibonacciHeap = new FibonacciHeap<int>();
|
||||
if(this.fibonacciHeap.Count != 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -59,24 +59,26 @@ namespace System.Collections.Tests
|
||||
{
|
||||
try
|
||||
{
|
||||
fibonacciHeap.Remove();
|
||||
this.fibonacciHeap.Remove();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch(IndexOutOfRangeException exception)
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
|
||||
}
|
||||
catch(Exception e)
|
||||
catch (Exception)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
this.fibonacciHeap.Add(i);
|
||||
}
|
||||
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
if (fibonacciHeap.Remove() != i)
|
||||
if (this.fibonacciHeap.Remove() != i)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -86,16 +88,17 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void DecreaseKeyTest()
|
||||
{
|
||||
fibonacciHeap.Add(5);
|
||||
fibonacciHeap.Add(10);
|
||||
fibonacciHeap.Add(7);
|
||||
fibonacciHeap.DecreaseKey(5, 3);
|
||||
if(fibonacciHeap.Contains(5) || !fibonacciHeap.Contains(3))
|
||||
this.fibonacciHeap.Add(5);
|
||||
this.fibonacciHeap.Add(10);
|
||||
this.fibonacciHeap.Add(7);
|
||||
this.fibonacciHeap.DecreaseKey(5, 3);
|
||||
if(this.fibonacciHeap.Contains(5) || !this.fibonacciHeap.Contains(3))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
fibonacciHeap.DecreaseKey(10, 1);
|
||||
if(fibonacciHeap.Remove() != 1)
|
||||
|
||||
this.fibonacciHeap.DecreaseKey(10, 1);
|
||||
if(this.fibonacciHeap.Remove() != 1)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -106,9 +109,10 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for(var i = 0; i < 10000; i++)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
this.fibonacciHeap.Add(i);
|
||||
}
|
||||
if (!fibonacciHeap.Contains(5124))
|
||||
|
||||
if (!this.fibonacciHeap.Contains(5124))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -119,11 +123,12 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for(var i = 0; i < 10000; i++)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
this.fibonacciHeap.Add(i);
|
||||
}
|
||||
fibonacciHeap.Remove();
|
||||
fibonacciHeap.Clear();
|
||||
if(fibonacciHeap.Count > 0)
|
||||
|
||||
this.fibonacciHeap.Remove();
|
||||
this.fibonacciHeap.Clear();
|
||||
if(this.fibonacciHeap.Count > 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -134,10 +139,11 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for(var i = 999; i >= 0; i--)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
this.fibonacciHeap.Add(i);
|
||||
}
|
||||
fibonacciHeap.Remove();
|
||||
var arr = fibonacciHeap.ToArray();
|
||||
|
||||
this.fibonacciHeap.Remove();
|
||||
var arr = this.fibonacciHeap.ToArray();
|
||||
|
||||
for(var i = 1; i < 512; i++)
|
||||
{
|
||||
@@ -153,18 +159,18 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 999; i >= 0; i--)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
this.fibonacciHeap.Add(i);
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
|
||||
foreach(var value in fibonacciHeap)
|
||||
foreach(var value in this.fibonacciHeap)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(value);
|
||||
count++;
|
||||
}
|
||||
|
||||
if(count == fibonacciHeap.Count)
|
||||
if(count == this.fibonacciHeap.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -178,17 +184,18 @@ namespace System.Collections.Tests
|
||||
var fibonacciHeap2 = new FibonacciHeap<int>();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
fibonacciHeap.Add(i);
|
||||
this.fibonacciHeap.Add(i);
|
||||
}
|
||||
|
||||
var serializer = new BinaryFormatter();
|
||||
var s = string.Empty;
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
serializer.Serialize(stream, fibonacciHeap);
|
||||
serializer.Serialize(stream, this.fibonacciHeap);
|
||||
stream.Position = 0;
|
||||
fibonacciHeap2 = (FibonacciHeap<int>)serializer.Deserialize(stream);
|
||||
}
|
||||
var enum1 = fibonacciHeap.GetEnumerator();
|
||||
|
||||
var enum1 = this.fibonacciHeap.GetEnumerator();
|
||||
var enum2 = fibonacciHeap2.GetEnumerator();
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
@@ -197,9 +204,9 @@ namespace System.Collections.Tests
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
enum1.MoveNext();
|
||||
enum2.MoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ using System.Collections.Generic;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.IO;
|
||||
|
||||
namespace System.Collections.Tests
|
||||
{
|
||||
namespace System.Collections.Tests;
|
||||
|
||||
[TestClass()]
|
||||
public class PriorityQueueTests
|
||||
{
|
||||
@@ -14,8 +14,8 @@ namespace System.Collections.Tests
|
||||
{
|
||||
try
|
||||
{
|
||||
priorityQueue = new PriorityQueue<int>();
|
||||
if(priorityQueue.Count > 0)
|
||||
this.priorityQueue = new PriorityQueue<int>();
|
||||
if(this.priorityQueue.Count > 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -31,9 +31,10 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for(var i = 0; i < 100; i++)
|
||||
{
|
||||
priorityQueue.Enqueue(i);
|
||||
this.priorityQueue.Enqueue(i);
|
||||
}
|
||||
if(priorityQueue.Count != 100)
|
||||
|
||||
if(this.priorityQueue.Count != 100)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -44,22 +45,25 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for(var i = 0; i < 100; i++)
|
||||
{
|
||||
priorityQueue.Enqueue(i);
|
||||
this.priorityQueue.Enqueue(i);
|
||||
}
|
||||
|
||||
for(var i = 0; i < 100; i++)
|
||||
{
|
||||
if(i != priorityQueue.Dequeue())
|
||||
if(i != this.priorityQueue.Dequeue())
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
if(priorityQueue.Count > 0)
|
||||
|
||||
if(this.priorityQueue.Count > 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
priorityQueue.Dequeue();
|
||||
this.priorityQueue.Dequeue();
|
||||
Assert.Fail();
|
||||
}
|
||||
catch
|
||||
@@ -71,8 +75,8 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void PeekTest()
|
||||
{
|
||||
priorityQueue.Enqueue(1051);
|
||||
if(priorityQueue.Peek() != 1051 && priorityQueue.Count != 1)
|
||||
this.priorityQueue.Enqueue(1051);
|
||||
if(this.priorityQueue.Peek() != 1051 && this.priorityQueue.Count != 1)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -84,17 +88,18 @@ namespace System.Collections.Tests
|
||||
var priorityQueue2 = new PriorityQueue<int>();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
priorityQueue.Enqueue(i);
|
||||
this.priorityQueue.Enqueue(i);
|
||||
}
|
||||
|
||||
var serializer = new BinaryFormatter();
|
||||
var s = string.Empty;
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
serializer.Serialize(stream, priorityQueue);
|
||||
serializer.Serialize(stream, this.priorityQueue);
|
||||
stream.Position = 0;
|
||||
priorityQueue2 = (PriorityQueue<int>)serializer.Deserialize(stream);
|
||||
}
|
||||
var enum1 = priorityQueue.GetEnumerator();
|
||||
|
||||
var enum1 = this.priorityQueue.GetEnumerator();
|
||||
var enum2 = priorityQueue2.GetEnumerator();
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
@@ -103,9 +108,9 @@ namespace System.Collections.Tests
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
enum1.MoveNext();
|
||||
enum2.MoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ using System.Collections.Generic;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.IO;
|
||||
|
||||
namespace System.Collections.Tests
|
||||
{
|
||||
namespace System.Collections.Tests;
|
||||
|
||||
[TestClass()]
|
||||
public class SkipListTests
|
||||
{
|
||||
@@ -12,13 +12,13 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void SkipListTest()
|
||||
{
|
||||
var skipList = new SkipList<int>();
|
||||
_ = new SkipList<int>();
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void SkipListTest2()
|
||||
{
|
||||
var skipList = new SkipList<int>(30);
|
||||
_ = new SkipList<int>(30);
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
@@ -26,7 +26,7 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for(var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
this.skipList.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,10 +35,11 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
this.skipList.Add(i);
|
||||
}
|
||||
skipList.Clear();
|
||||
if(skipList.Count > 0)
|
||||
|
||||
this.skipList.Clear();
|
||||
if(this.skipList.Count > 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -49,10 +50,10 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
this.skipList.Add(i);
|
||||
}
|
||||
|
||||
if (!skipList.Contains(50))
|
||||
if (!this.skipList.Contains(50))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -63,10 +64,11 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
this.skipList.Add(i);
|
||||
}
|
||||
var array = new int[skipList.Count];
|
||||
skipList.CopyTo(array, 0);
|
||||
|
||||
var array = new int[this.skipList.Count];
|
||||
this.skipList.CopyTo(array, 0);
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
if(array[i] != i)
|
||||
@@ -81,9 +83,10 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
this.skipList.Add(i);
|
||||
}
|
||||
var array = skipList.ToArray();
|
||||
|
||||
var array = this.skipList.ToArray();
|
||||
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
@@ -99,10 +102,10 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
this.skipList.Add(i);
|
||||
}
|
||||
|
||||
foreach(var i in skipList)
|
||||
foreach(var i in this.skipList)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(i);
|
||||
}
|
||||
@@ -113,10 +116,11 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
this.skipList.Add(i);
|
||||
}
|
||||
skipList.Remove(50);
|
||||
if (skipList.Contains(50))
|
||||
|
||||
this.skipList.Remove(50);
|
||||
if (this.skipList.Contains(50))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -129,17 +133,18 @@ namespace System.Collections.Tests
|
||||
var skipList2 = new SkipList<int>();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
skipList.Add(i);
|
||||
this.skipList.Add(i);
|
||||
}
|
||||
|
||||
var serializer = new BinaryFormatter();
|
||||
var s = string.Empty;
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
serializer.Serialize(stream, skipList);
|
||||
serializer.Serialize(stream, this.skipList);
|
||||
stream.Position = 0;
|
||||
skipList2 = (SkipList<int>)serializer.Deserialize(stream);
|
||||
}
|
||||
var enum1 = skipList.GetEnumerator();
|
||||
|
||||
var enum1 = this.skipList.GetEnumerator();
|
||||
var enum2 = skipList2.GetEnumerator();
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
@@ -148,9 +153,9 @@ namespace System.Collections.Tests
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
enum1.MoveNext();
|
||||
enum2.MoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ using System.Collections.Generic;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.IO;
|
||||
|
||||
namespace System.Collections.Tests
|
||||
{
|
||||
namespace System.Collections.Tests;
|
||||
|
||||
[TestClass()]
|
||||
public class TreapTests
|
||||
{
|
||||
@@ -12,7 +12,7 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void TreapTest()
|
||||
{
|
||||
treap = new Treap<int>();
|
||||
this.treap = new Treap<int>();
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
@@ -21,18 +21,18 @@ namespace System.Collections.Tests
|
||||
var random = new Random();
|
||||
for(var i = 0; i < 1000; i++)
|
||||
{
|
||||
treap.Add(random.Next(0, 5000));
|
||||
this.treap.Add(random.Next(0, 5000));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod()]
|
||||
public void RemoveTest()
|
||||
{
|
||||
treap.Add(60);
|
||||
treap.Add(6);
|
||||
treap.Add(5);
|
||||
treap.Remove(60);
|
||||
if(treap.Contains(60) || treap.Count > 2)
|
||||
this.treap.Add(60);
|
||||
this.treap.Add(6);
|
||||
this.treap.Add(5);
|
||||
this.treap.Remove(60);
|
||||
if(this.treap.Contains(60) || this.treap.Count > 2)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -44,10 +44,11 @@ namespace System.Collections.Tests
|
||||
var random = new Random();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
treap.Add(random.Next(0, 5000));
|
||||
this.treap.Add(random.Next(0, 5000));
|
||||
}
|
||||
treap.Clear();
|
||||
if(treap.Count > 0)
|
||||
|
||||
this.treap.Clear();
|
||||
if(this.treap.Count > 0)
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -56,13 +57,13 @@ namespace System.Collections.Tests
|
||||
[TestMethod()]
|
||||
public void ContainsTest()
|
||||
{
|
||||
treap.Add(50);
|
||||
treap.Add(25);
|
||||
treap.Add(991142);
|
||||
treap.Add(12313);
|
||||
treap.Add(24);
|
||||
treap.Add(23);
|
||||
if (!treap.Contains(24))
|
||||
this.treap.Add(50);
|
||||
this.treap.Add(25);
|
||||
this.treap.Add(991142);
|
||||
this.treap.Add(12313);
|
||||
this.treap.Add(24);
|
||||
this.treap.Add(23);
|
||||
if (!this.treap.Contains(24))
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
@@ -73,9 +74,10 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for(var i = 0; i < 1000; i++)
|
||||
{
|
||||
treap.Add(i);
|
||||
this.treap.Add(i);
|
||||
}
|
||||
var arr = treap.ToArray();
|
||||
|
||||
var arr = this.treap.ToArray();
|
||||
for(var i = 0; i < 1000; i++)
|
||||
{
|
||||
if(arr[i] != i)
|
||||
@@ -90,17 +92,17 @@ namespace System.Collections.Tests
|
||||
{
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
treap.Add(i);
|
||||
this.treap.Add(i);
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
foreach(var value in treap)
|
||||
foreach(var value in this.treap)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(value);
|
||||
count++;
|
||||
}
|
||||
|
||||
if(count == treap.Count)
|
||||
if(count == this.treap.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -115,17 +117,18 @@ namespace System.Collections.Tests
|
||||
var treap2 = new Treap<int>();
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
treap.Add(i);
|
||||
this.treap.Add(i);
|
||||
}
|
||||
|
||||
var serializer = new BinaryFormatter();
|
||||
var s = string.Empty;
|
||||
using (var stream = new MemoryStream())
|
||||
{
|
||||
serializer.Serialize(stream, treap);
|
||||
serializer.Serialize(stream, this.treap);
|
||||
stream.Position = 0;
|
||||
treap2 = (Treap<int>)serializer.Deserialize(stream);
|
||||
}
|
||||
var enum1 = treap.GetEnumerator();
|
||||
|
||||
var enum1 = this.treap.GetEnumerator();
|
||||
var enum2 = treap2.GetEnumerator();
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
@@ -134,9 +137,9 @@ namespace System.Collections.Tests
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
enum1.MoveNext();
|
||||
enum2.MoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace System.Extensions.Tests
|
||||
{
|
||||
namespace System.Extensions.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class OptionalTests
|
||||
{
|
||||
@@ -108,4 +108,3 @@ namespace System.Extensions.Tests
|
||||
newNullValue.Should().Be(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace System.Extensions.Tests
|
||||
{
|
||||
namespace System.Extensions.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class ResultTests
|
||||
{
|
||||
@@ -114,4 +114,3 @@ namespace System.Extensions.Tests
|
||||
failureOptional.Should().NotBeNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SystemExtensionsTests.Utils;
|
||||
|
||||
namespace System.Http.Tests
|
||||
{
|
||||
namespace System.Net.Http.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class HttpClientTests
|
||||
{
|
||||
@@ -316,4 +314,3 @@ namespace System.Http.Tests
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SystemExtensions.NetStandard.Tests.Logging.Models
|
||||
{
|
||||
namespace SystemExtensions.NetStandard.Tests.Logging.Models;
|
||||
|
||||
public sealed class CachingLogger<T> : ILogger<T>
|
||||
{
|
||||
public List<string> LogCache { get; } = new();
|
||||
@@ -24,4 +24,3 @@ namespace SystemExtensions.NetStandard.Tests.Logging.Models
|
||||
this.LogCache.Add(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,8 @@ using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using SystemExtensions.NetStandard.Tests.Logging.Models;
|
||||
|
||||
namespace System.Logging.Tests
|
||||
{
|
||||
namespace System.Logging.Tests;
|
||||
|
||||
[TestClass]
|
||||
public class ScopedLoggerTests
|
||||
{
|
||||
@@ -33,15 +33,9 @@ namespace System.Logging.Tests
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateLogger_NullFlow_ThrowsArgumentNullException()
|
||||
public void CreateLogger_NullFlow_ReturnsScopedLogger()
|
||||
{
|
||||
var action = new Action(() =>
|
||||
{
|
||||
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.CreateLogger_NullFlow_ThrowsArgumentNullException), null);
|
||||
});
|
||||
|
||||
|
||||
action.Should().Throw<ArgumentNullException>();
|
||||
var scopedLogger = this.cachingLogger.CreateScopedLogger(nameof(this.CreateLogger_NullFlow_ReturnsScopedLogger), null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -263,4 +257,3 @@ namespace System.Logging.Tests
|
||||
this.cachingLogger.LogCache.First().Should().Be(expectedMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user