Compare commits

..

28 Commits

Author SHA1 Message Date
amacocian 0e868d9597 Merge 7a764a5929 into 5aaa0d318a 2021-07-10 08:00:09 +00:00
Alexandru Macocian 7a764a5929 Dependency Injection extensions 2021-07-10 10:59:27 +03:00
amacocian 5aaa0d318a Merge pull request #1 from AlexMacocian/alexmacocian/add-pipelines
Added CI&CD pipelines
2021-06-02 13:04:46 +02:00
Alexandru Macocian 5767ccfd70 Fix misnaming in CI pipeline
Disable CD pipeline for PRs
2021-06-02 13:02:01 +02:00
Alexandru Macocian 16a9208e07 Added CI&CD pipelines
Changed test project to .net5
Changed ThreadPool to use CancellationTokens
2021-06-02 12:58:04 +02:00
Alexandru Macocian 3038661f6d Mockable http client implementation. 2021-05-13 13:55:17 +02:00
Alexandru Macocian 035e58248e Updated to 1.1.4 2021-04-23 10:52:13 +02:00
Alexandru Macocian 0d418ac9bf Merge branch 'master' of https://github.com/AlexMacocian/SystemExtensions 2021-04-23 10:49:50 +02:00
Alexandru Macocian 0288b385a0 String IsNullOrWhiteSpace and IsNullOrEmpty extensions. 2021-04-23 10:49:41 +02:00
Alexandru Macocian 5d442580c3 Add linq extension Do 2021-04-03 14:44:17 +02:00
Alexandru Macocian ee341af2c3 Read until extension. 2021-04-01 14:43:18 +02:00
Alexandru Macocian 8d1355ecbc Include repository 2021-04-01 12:49:44 +02:00
Alexandru Macocian c04b6ba906 Include author name 2021-04-01 12:49:04 +02:00
Alexandru Macocian 9a7125fbb0 Added various extensions.
Added coding style helpers.
Unit tests.
2021-04-01 12:38:26 +02:00
Alexandru Macocian 66b766326b Use license file from repo 2021-03-26 12:00:53 +01:00
Alexandru Macocian c8a98a0494 Merge 2021-03-26 11:59:12 +01:00
Alexandru Macocian f39e8cf89e Port to netstandard.
Nit fixes.
Fixed e2e tests.
Added MIT license.
2021-03-26 11:58:07 +01:00
Alexandru Macocian 0b5e93f9ea Changed package id 2020-07-27 11:21:22 +02:00
Alexandru Macocian 8fd22b3644 Restructured project to new project style
Targeted netstandard 2.0
Built nuget package
2020-07-27 11:18:56 +02:00
amacocian f6069bd3aa Bit field structures. 2019-12-09 10:44:16 +01:00
amacocian 89159e6cba Merge branch 'master' of https://github.com/AlexMacocian/SystemExtensions 2019-09-16 08:41:45 +03:00
amacocian a608b1ac95 changed proj details 2019-09-16 08:41:33 +03:00
amacocian 2ebd821bbd Cleaned code and upgraded framework to 4.7.2. 2019-07-19 11:10:34 +03:00
amacocian f0a5d509ea Implemented another way to get current process filename 2019-07-15 10:47:09 +03:00
amacocian 9003157a0f Changed elevateprocess way of getting the filename 2019-07-15 10:42:45 +03:00
amacocian 47c1e67f38 Implemented basic application functionality and security. 2019-07-15 10:36:50 +03:00
amacocian 5cb4b3a512 Removed a mistake in code 2019-07-11 09:49:00 +03:00
amacocian e8c9e682ed Marked class as sealed 2019-07-11 09:46:22 +03:00
83 changed files with 4100 additions and 669 deletions
+64
View File
@@ -0,0 +1,64 @@
name: SystemExtensions CD Pipeline
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
environment: Default
strategy:
matrix:
targetplatform: [x64]
runs-on: windows-latest
env:
Configuration: Release
Solution_Path: SystemExtensions.sln
Test_Project_Path: SystemExtensions.Tests\SystemExtensions.NetStandard.Tests.csproj
DI_Test_Project_Path: SystemExtensions.DependencyInjection.Tests\SystemExtensions.NetStandard.DependencyInjection.Tests.csproj
Source_Project_Path: SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj
Actions_Allow_Unsecure_Commands: true
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Install .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.202'
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.0.1
- name: Restore project
run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
env:
RuntimeIdentifier: win-${{ matrix.targetplatform }}
- name: Build SystemExtensions.NetStandard project
run: dotnet build SystemExtensions.NetStandard -c $env:Configuration
- name: Build SystemExtensions.NetStandard.DependencyInjection project
run: dotnet build SystemExtensions.NetStandard.DependencyInjection -c $env:Configuration
- name: Push 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: Push 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}}
+52
View File
@@ -0,0 +1,52 @@
name: SystemExtensions CI Pipeline
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
strategy:
matrix:
targetplatform: [x64]
runs-on: windows-latest
env:
Solution_Path: SystemExtensions.sln
Test_Project_Path: SystemExtensions.Tests\SystemExtensions.NetStandard.Tests.csproj
DI_Test_Project_Path: SystemExtensions.DependencyInjection.Tests\SystemExtensions.NetStandard.DependencyInjection.Tests.csproj
Source_Project_Path: SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj
Actions_Allow_Unsecure_Commands: true
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Install .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '5.0.202'
- name: Setup MSBuild.exe
uses: microsoft/setup-msbuild@v1.0.1
- name: Execute Unit Tests
run: dotnet test $env:Test_Project_Path
- name: Execute DI Unit Tests
run: dotnet test $env:DI_Test_Project_Path
- name: Restore Project
run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
env:
Configuration: Debug
RuntimeIdentifier: win-${{ matrix.targetplatform }}
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2019 Macocian Alexandru Victor
Copyright (c) 2021 Macocian Alexandru Victor
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,26 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Extensions.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class DefaultOptionsManagerTests
{
private readonly DefaultOptionsManager optionsManager = new();
[TestMethod]
public void GetOptions_ReturnsDefault()
{
var options = this.optionsManager.GetOptions<string>();
options.Should().BeNull();
}
[TestMethod]
public void UpdateOptions_Succeeds()
{
this.optionsManager.UpdateOptions(string.Empty);
}
}
}
@@ -0,0 +1,6 @@
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
public sealed class DummyOptions
{
}
}
@@ -0,0 +1,69 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Extensions.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class LiveOptionsResolverTests
{
private readonly LiveOptionsResolver liveOptionsResolver = new();
private readonly Mock<Slim.IServiceProvider> serviceProviderMock = new();
private readonly Mock<IOptionsManager> optionsManagerMock = new();
[TestMethod]
public void CanResolve_ILiveOptions_ReturnsTrue()
{
var type = typeof(ILiveOptions<string>);
var canResolve = this.liveOptionsResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_AnythingElse_ReturnsFalse()
{
var types = new Type[] { typeof(object), typeof(string), typeof(LiveOptionsResolverTests), typeof(int) };
foreach (var type in types)
{
var canResolve = this.liveOptionsResolver.CanResolve(type);
canResolve.Should().BeFalse();
}
}
[TestMethod]
public void Resolve_ILiveOptions_ReturnsILiveOptions()
{
this.SetupServiceProvider();
var liveOptions = this.liveOptionsResolver.Resolve(this.serviceProviderMock.Object, typeof(ILiveOptions<string>));
liveOptions.Should().BeAssignableTo<ILiveOptions<string>>();
}
[TestMethod]
public void Resolve_AnythingElse_Throws()
{
this.SetupServiceProvider();
Action action = new(() =>
{
this.liveOptionsResolver.Resolve(this.serviceProviderMock.Object, typeof(string));
});
action.Should().Throw<Exception>();
}
private void SetupServiceProvider()
{
this.serviceProviderMock
.Setup(u => u.GetService<IOptionsManager>())
.Returns(this.optionsManagerMock.Object);
}
}
}
@@ -0,0 +1,69 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Extensions.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class LiveUpdateableOptionsResolverTests
{
private readonly LiveUpdateableOptionsResolver liveUpdateableOptionsResolver = new();
private readonly Mock<Slim.IServiceProvider> serviceProviderMock = new();
private readonly Mock<IOptionsManager> optionsManagerMock = new();
[TestMethod]
public void CanResolve_ILiveUpdateableOptions_ReturnsTrue()
{
var type = typeof(ILiveUpdateableOptions<string>);
var canResolve = this.liveUpdateableOptionsResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_AnythingElse_ReturnsFalse()
{
var types = new Type[] { typeof(object), typeof(string), typeof(LiveOptionsResolverTests), typeof(int) };
foreach (var type in types)
{
var canResolve = this.liveUpdateableOptionsResolver.CanResolve(type);
canResolve.Should().BeFalse();
}
}
[TestMethod]
public void Resolve_ILiveUpdateableOptions_ReturnsILiveUpdateableOptions()
{
this.SetupServiceProvider();
var liveOptions = this.liveUpdateableOptionsResolver.Resolve(this.serviceProviderMock.Object, typeof(ILiveUpdateableOptions<string>));
liveOptions.Should().BeAssignableTo<ILiveUpdateableOptions<string>>();
}
[TestMethod]
public void Resolve_AnythingElse_Throws()
{
this.SetupServiceProvider();
Action action = new(() =>
{
this.liveUpdateableOptionsResolver.Resolve(this.serviceProviderMock.Object, typeof(string));
});
action.Should().Throw<Exception>();
}
private void SetupServiceProvider()
{
this.serviceProviderMock
.Setup(u => u.GetService<IOptionsManager>())
.Returns(this.optionsManagerMock.Object);
}
}
}
@@ -0,0 +1,44 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Extensions.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class LiveUpdateableOptionsWrapperTests
{
private LiveUpdateableOptionsWrapper<string> optionsWrapper;
private readonly Mock<IOptionsManager> optionsManagerMock = new();
[TestInitialize]
public void TestInitialize()
{
this.optionsWrapper = new LiveUpdateableOptionsWrapper<string>(this.optionsManagerMock.Object);
}
[TestMethod]
public void GetValue_ReturnsValue()
{
this.optionsManagerMock
.Setup(u => u.GetOptions<string>())
.Returns("hello");
var value = this.optionsWrapper.Value;
value.Should().Be("hello");
}
[TestMethod]
public void UpdateOption_CallsOptionsManager()
{
this.optionsManagerMock
.Setup(u => u.UpdateOptions<string>(It.IsAny<string>()))
.Verifiable();
this.optionsWrapper.UpdateOption();
this.optionsManagerMock.Verify();
}
}
}
@@ -0,0 +1,72 @@
using FluentAssertions;
using Microsoft.Extensions.Options;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Extensions.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;
[TestMethod]
public void CanResolve_ILiveOptions_ReturnsTrue()
{
var type = typeof(IOptions<string>);
var canResolve = this.optionsResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_AnythingElse_ReturnsFalse()
{
var types = new Type[] { typeof(object), typeof(string), typeof(OptionsResolverTests), typeof(int) };
foreach (var type in types)
{
var canResolve = this.optionsResolver.CanResolve(type);
canResolve.Should().BeFalse();
}
}
[TestMethod]
public void Resolve_IOptions_ReturnsIOptions()
{
this.SetupServiceProvider();
var liveOptions = this.optionsResolver.Resolve(this.serviceProviderMock.Object, typeof(IOptions<string>));
liveOptions.Should().BeAssignableTo<IOptions<string>>();
}
[TestMethod]
public void Resolve_AnythingElse_Throws()
{
this.SetupServiceProvider();
Action action = new(() =>
{
this.optionsResolver.Resolve(this.serviceProviderMock.Object, typeof(string));
});
action.Should().Throw<Exception>();
}
private void SetupServiceProvider()
{
this.serviceProviderMock
.Setup(u => u.GetService<IOptionsManager>())
.Returns(this.OptionsManagerMock.Object);
}
}
}
@@ -0,0 +1,69 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Extensions.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class UpdateableOptionsResolverTests
{
private readonly UpdateableOptionsResolver updateableOptionsResolver = new();
private readonly Mock<Slim.IServiceProvider> serviceProviderMock = new();
private readonly Mock<IOptionsManager> optionsManagerMock = new();
[TestMethod]
public void CanResolve_ILiveOptions_ReturnsTrue()
{
var type = typeof(IUpdateableOptions<string>);
var canResolve = this.updateableOptionsResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_AnythingElse_ReturnsFalse()
{
var types = new Type[] { typeof(object), typeof(string), typeof(UpdateableOptionsResolverTests), typeof(int) };
foreach (var type in types)
{
var canResolve = this.updateableOptionsResolver.CanResolve(type);
canResolve.Should().BeFalse();
}
}
[TestMethod]
public void Resolve_IUpdateableOptions_ReturnsIUpdateableOptions()
{
this.SetupServiceProvider();
var liveOptions = this.updateableOptionsResolver.Resolve(this.serviceProviderMock.Object, typeof(IUpdateableOptions<string>));
liveOptions.Should().BeAssignableTo<IUpdateableOptions<string>>();
}
[TestMethod]
public void Resolve_AnythingElse_Throws()
{
this.SetupServiceProvider();
Action action = new(() =>
{
this.updateableOptionsResolver.Resolve(this.serviceProviderMock.Object, typeof(string));
});
action.Should().Throw<Exception>();
}
private void SetupServiceProvider()
{
this.serviceProviderMock
.Setup(u => u.GetService<IOptionsManager>())
.Returns(this.optionsManagerMock.Object);
}
}
}
@@ -0,0 +1,47 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Extensions.Configuration;
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
[TestClass]
public class UpdateableOptionsWrapperTests
{
private const string Value = "hello";
private UpdateableOptionsWrapper<string> optionsWrapper;
private readonly Mock<IOptionsManager> optionsManagerMock = new();
[TestInitialize]
public void TestInitialize()
{
this.optionsWrapper = new UpdateableOptionsWrapper<string>(optionsManagerMock.Object, Value);
}
[TestMethod]
public void GetValue_ReturnsValue()
{
this.optionsManagerMock
.Setup(u => u.GetOptions<string>())
.Throws<Exception>();
var value = this.optionsWrapper.Value;
value.Should().Be(Value);
}
[TestMethod]
public void UpdateOption_CallsOptionsManager()
{
this.optionsManagerMock
.Setup(u => u.UpdateOptions<string>(It.IsAny<string>()))
.Verifiable();
this.optionsWrapper.UpdateOption();
this.optionsManagerMock.Verify();
}
}
}
@@ -0,0 +1,69 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Http;
using System.Net.Http;
namespace SystemExtensions.DependencyInjection.Tests.Http
{
[TestClass]
public class HttpClientResolverTests
{
private readonly HttpClientResolver httpClientResolver = new();
private readonly Mock<Slim.IServiceProvider> serviceProviderMock = new();
[TestMethod]
public void CanResolve_IHttpClient_ReturnsTrue()
{
var type = typeof(IHttpClient<>);
var canResolve = this.httpClientResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_AnythingElse_ReturnsFalse()
{
var types = new Type[] { typeof(HttpClient), typeof(object), typeof(string), typeof(HttpClientResolverTests), typeof(int) };
foreach (var type in types)
{
var canResolve = this.httpClientResolver.CanResolve(type);
canResolve.Should().BeFalse();
}
}
[TestMethod]
public void Resolve_TypedClient_ReturnsIHttpClient()
{
var client = this.httpClientResolver.Resolve(this.serviceProviderMock.Object, typeof(IHttpClient<string>));
client.Should().BeAssignableTo<IHttpClient<string>>();
}
[TestMethod]
public void Resolve_NonGenericType_Throws()
{
Action action = new(() =>
{
this.httpClientResolver.Resolve(this.serviceProviderMock.Object, typeof(IHttpClient<>));
});
action.Should().Throw<Exception>();
}
[TestMethod]
public void Resolve_RandomType_Throws()
{
Action action = new(() =>
{
this.httpClientResolver.Resolve(this.serviceProviderMock.Object, typeof(string));
});
action.Should().Throw<Exception>();
}
}
}
@@ -0,0 +1,43 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Logging;
namespace SystemExtensions.DependencyInjection.Tests.Logging
{
[TestClass]
public class CVLoggerProviderTests
{
private readonly Mock<ILogsWriter> logsWriterMock = new();
private CVLoggerProvider cVLoggerProvider;
[TestInitialize]
public void TestInitialize()
{
this.cVLoggerProvider = new CVLoggerProvider(this.logsWriterMock.Object);
}
[TestMethod]
public void CreateLogger_CreatesNewLogger()
{
var logger = this.cVLoggerProvider.CreateLogger(string.Empty);
logger.Should().NotBeNull();
}
[TestMethod]
public void LogEntry_CallsLogWriter()
{
this.cVLoggerProvider.LogEntry(new Log());
this.logsWriterMock.Verify();
}
private void SetupLogsWriter()
{
this.logsWriterMock
.Setup(u => u.WriteLog(It.IsAny<Log>()))
.Verifiable();
}
}
}
@@ -0,0 +1,76 @@
using FluentAssertions;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Logging;
namespace SystemExtensions.DependencyInjection.Tests.Logging
{
[TestClass]
public class CVLoggerTests
{
private readonly Mock<ICVLoggerProvider> cvLoggerProviderMock = new();
private CVLogger cVLogger;
[TestInitialize]
public void TestInitialize()
{
this.cVLogger = new CVLogger(string.Empty, this.cvLoggerProviderMock.Object);
}
[TestMethod]
public void BeginScope_ReturnsNull()
{
var scope = this.cVLogger.BeginScope(string.Empty);
scope.Should().BeNull();
}
[TestMethod]
[DataRow(LogLevel.Debug)]
[DataRow(LogLevel.Trace)]
[DataRow(LogLevel.Information)]
[DataRow(LogLevel.Warning)]
[DataRow(LogLevel.Error)]
[DataRow(LogLevel.Critical)]
public void IsEnabled_OnAllLogLevels_ReturnsTrue(LogLevel logLevel)
{
var enabled = this.cVLogger.IsEnabled(logLevel);
enabled.Should().BeTrue();
}
[TestMethod]
public void Log_CallsFormatter()
{
var called = false;
Func<string, Exception, string> messageFormatter = new((state, exception) =>
{
called = true;
return string.Empty;
});
this.cVLogger.Log(LogLevel.Debug, new EventId(), "Some message", new Exception(), messageFormatter);
called.Should().BeTrue();
}
[TestMethod]
public void Log_CallsLogsProvider()
{
this.SetupLoggerProvider();
this.cVLogger.Log(LogLevel.Debug, new EventId(), "Some message", new Exception(), new Func<string, Exception, string>((s, e) => string.Empty));
this.cvLoggerProviderMock.Verify();
}
private void SetupLoggerProvider()
{
this.cvLoggerProviderMock
.Setup(u => u.LogEntry(It.IsAny<Log>()))
.Verifiable();
}
}
}
@@ -0,0 +1,30 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Logging;
namespace SystemExtensions.DependencyInjection.Tests.Logging
{
[TestClass]
public class DebugLogsWriterTests
{
private readonly DebugLogsWriter logsWriter = new();
[TestMethod]
public void WriteLog_Succeeds()
{
this.logsWriter.WriteLog(new Log());
}
[TestMethod]
public void WriteNullLog_Throws()
{
Action action = new(() =>
{
this.logsWriter.WriteLog(null);
});
action.Should().Throw<Exception>();
}
}
}
@@ -0,0 +1,109 @@
using FluentAssertions;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Logging;
using System.Windows.Extensions.Logging;
namespace SystemExtensions.DependencyInjection.Tests.Logging
{
[TestClass]
public class LoggerResolverTests
{
private readonly Mock<Slim.IServiceProvider> serviceProviderMock = new();
private readonly Mock<ILoggerFactory> loggerFactoryMock = new();
private readonly Mock<ILogger> loggerMock = new();
private readonly LoggerResolver loggerResolver = new();
[TestMethod]
public void CanResolve_ILogger_ReturnsTrue()
{
var type = typeof(ILogger);
var canResolve = this.loggerResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_GenericILogger_ReturnsTrue()
{
var type = typeof(ILogger<string>);
var canResolve = this.loggerResolver.CanResolve(type);
canResolve.Should().BeTrue();
}
[TestMethod]
public void CanResolve_AnythingElse_ReturnsFalse()
{
var types = new Type[] { typeof(CVLogger), typeof(object), typeof(string), typeof(LoggerResolverTests), typeof(int) };
foreach(var type in types)
{
var canResolve = this.loggerResolver.CanResolve(type);
canResolve.Should().BeFalse();
}
}
[TestMethod]
public void Resolve_ILogger_ReturnsILogger()
{
this.SetupIServiceProvider();
var logger = this.loggerResolver.Resolve(this.serviceProviderMock.Object, typeof(ILogger));
logger.Should().BeAssignableTo<ILogger>();
}
[TestMethod]
public void Resolve_TypedILogger_ReturnsTypedILogger()
{
this.SetupIServiceProvider();
var logger = this.loggerResolver.Resolve(this.serviceProviderMock.Object, typeof(ILogger<string>));
logger.Should().BeAssignableTo<ILogger<string>>();
}
[TestMethod]
public void Resolve_RandomType_Throws()
{
this.SetupIServiceProvider();
Action action = new(() =>
{
this.loggerResolver.Resolve(this.serviceProviderMock.Object, typeof(string));
});
action.Should().Throw<Exception>();
}
[TestMethod]
public void Resolve_NonTypedGeneric_Throws()
{
this.SetupIServiceProvider();
Action action = new(() =>
{
this.loggerResolver.Resolve(this.serviceProviderMock.Object, typeof(ILogger<>));
});
action.Should().Throw<Exception>();
}
private void SetupIServiceProvider()
{
this.serviceProviderMock
.Setup(u => u.GetService<ILoggerFactory>())
.Returns(this.loggerFactoryMock.Object);
this.loggerFactoryMock
.Setup(u => u.CreateLogger(It.IsAny<string>()))
.Returns(this.loggerMock.Object);
}
}
}
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
</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" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SystemExtensions.NetStandard.DependencyInjection\SystemExtensions.NetStandard.DependencyInjection.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,14 @@
namespace System.Extensions.Configuration
{
public sealed class DefaultOptionsManager : IOptionsManager
{
public T GetOptions<T>() where T : class
{
return default;
}
public void UpdateOptions<T>(T value) where T : class
{
}
}
}
@@ -0,0 +1,9 @@
using Microsoft.Extensions.Options;
namespace System.Extensions.Configuration
{
public interface ILiveOptions<T> : IOptions<T>
where T : class
{
}
}
@@ -0,0 +1,7 @@
namespace System.Extensions.Configuration
{
public interface ILiveUpdateableOptions<T> : ILiveOptions<T>, IUpdateableOptions<T>
where T : class
{
}
}
@@ -0,0 +1,10 @@
namespace System.Extensions.Configuration
{
public interface IOptionsManager
{
T GetOptions<T>()
where T : class;
void UpdateOptions<T>(T value)
where T : class;
}
}
@@ -0,0 +1,13 @@
using Microsoft.Extensions.Options;
namespace System.Extensions.Configuration
{
public interface IUpdateableOptions<out T> : IOptions<T>
where T : class
{
/// <summary>
/// Updates the configuration with the current value stored in <see cref="IOptions{TOptions}.Value"/>.
/// </summary>
void UpdateOption();
}
}
@@ -0,0 +1,27 @@
using Slim.Resolvers;
namespace System.Extensions.Configuration
{
public sealed class LiveOptionsResolver : IDependencyResolver
{
private static readonly Type optionsType = typeof(LiveUpdateableOptionsWrapper<>);
public bool CanResolve(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ILiveOptions<>))
{
return true;
}
return false;
}
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
{
var typedOptionsType = optionsType.MakeGenericType(type.GetGenericArguments());
var configurationManager = serviceProvider.GetService<IOptionsManager>();
return Activator.CreateInstance(typedOptionsType, configurationManager);
}
}
}
@@ -0,0 +1,26 @@
using Slim.Resolvers;
namespace System.Extensions.Configuration
{
public sealed class LiveUpdateableOptionsResolver : IDependencyResolver
{
private static readonly Type optionsType = typeof(LiveUpdateableOptionsWrapper<>);
public bool CanResolve(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ILiveUpdateableOptions<>))
{
return true;
}
return false;
}
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
{
var typedOptionsType = optionsType.MakeGenericType(type.GetGenericArguments());
var configurationManager = serviceProvider.GetService<IOptionsManager>();
return Activator.CreateInstance(typedOptionsType, configurationManager);
}
}
}
@@ -0,0 +1,31 @@
using System.Extensions;
namespace System.Extensions.Configuration
{
public sealed class LiveUpdateableOptionsWrapper<T> : ILiveUpdateableOptions<T>
where T : class
{
private readonly IOptionsManager configurationManager;
private T value;
public T Value
{
get
{
this.value = this.configurationManager.GetOptions<T>();
return this.value;
}
}
public LiveUpdateableOptionsWrapper(IOptionsManager configurationManager)
{
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
}
public void UpdateOption()
{
this.configurationManager.UpdateOptions<T>(this.value);
}
}
}
@@ -0,0 +1,33 @@
using Microsoft.Extensions.Options;
using Slim.Resolvers;
namespace System.Extensions.Configuration
{
public sealed class OptionsResolver : IDependencyResolver
{
private static readonly Type optionsType = typeof(OptionsWrapper<>);
private static readonly Type configurationType = typeof(IOptionsManager);
public bool CanResolve(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IOptions<>))
{
return true;
}
return false;
}
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
{
var typedOptionsType = optionsType.MakeGenericType(type.GetGenericArguments());
var configurationManager = serviceProvider.GetService<IOptionsManager>();
var optionsValue = configurationType
.GetMethod(nameof(IOptionsManager.GetOptions))
.MakeGenericMethod(type.GetGenericArguments())
.Invoke(configurationManager, Array.Empty<object>());
return Activator.CreateInstance(typedOptionsType, optionsValue);
}
}
}
@@ -0,0 +1,32 @@
using Slim.Resolvers;
namespace System.Extensions.Configuration
{
public sealed class UpdateableOptionsResolver : IDependencyResolver
{
private static readonly Type optionsType = typeof(UpdateableOptionsWrapper<>);
private static readonly Type configurationType = typeof(IOptionsManager);
public bool CanResolve(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IUpdateableOptions<>))
{
return true;
}
return false;
}
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
{
var typedOptionsType = optionsType.MakeGenericType(type.GetGenericArguments());
var configurationManager = serviceProvider.GetService<IOptionsManager>();
var optionsValue = configurationType
.GetMethod(nameof(IOptionsManager.GetOptions))
.MakeGenericMethod(type.GetGenericArguments())
.Invoke(configurationManager, Array.Empty<object>());
return Activator.CreateInstance(typedOptionsType, configurationManager, optionsValue);
}
}
}
@@ -0,0 +1,23 @@
using System.Extensions;
namespace System.Extensions.Configuration
{
public sealed class UpdateableOptionsWrapper<T> : IUpdateableOptions<T>
where T : class
{
private readonly IOptionsManager configurationManager;
public T Value { get; }
public UpdateableOptionsWrapper(IOptionsManager configurationManager, T options)
{
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
this.Value = options;
}
public void UpdateOption()
{
this.configurationManager.UpdateOptions(this.Value);
}
}
}
@@ -0,0 +1,142 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Slim;
using System.Extensions;
using System.Extensions.Configuration;
using System.Http;
using System.Logging;
using System.Net.Http;
namespace System.Extensions
{
public static class ServiceManagerExtensions
{
/// <summary>
/// Registers a <see cref="IOptionsManager"/> with the default <see cref="DefaultOptionsManager"/>.
/// This call also registers the resolver that resolves <see cref="IUpdateableOptions{T}"/> and <see cref="IOptions{T}"/>.
/// </summary>
/// <param name="serviceManager"><see cref="IServiceManager"/>.</param>
/// <returns>Provided <see cref="IServiceManager"/>.</returns>
public static IServiceManager RegisterOptionsManager(this IServiceManager serviceManager)
{
serviceManager.RegisterSingleton<IOptionsManager, DefaultOptionsManager>();
serviceManager.RegisterOptionsResolver();
return serviceManager;
}
/// <summary>
/// Registers a <see cref="IOptionsManager"/>.
/// This call also registers the resolver that resolves <see cref="IUpdateableOptions{T}"/> and <see cref="IOptions{T}"/>.
/// </summary>
/// <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)
where T : IOptionsManager
{
serviceManager.RegisterSingleton<IOptionsManager, T>();
serviceManager.RegisterOptionsResolver();
return serviceManager;
}
/// <summary>
/// Registers resolvers for <see cref="IOptions{TOptions}"/> and <see cref="IUpdateableOptions{T}"/>.
/// Depends on a <see cref="IOptionsManager"/> in order to properly resolve options.
/// </summary>
/// <param name="serviceManager"><see cref="IServiceManager"/>.</param>
/// <returns><see cref="IServiceManager"/>.</returns>
public static IServiceManager RegisterOptionsResolver(this IServiceManager serviceManager)
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterResolver(new OptionsResolver());
serviceManager.RegisterResolver(new UpdateableOptionsResolver());
serviceManager.RegisterResolver(new LiveOptionsResolver());
serviceManager.RegisterResolver(new LiveUpdateableOptionsResolver());
return serviceManager;
}
/// <summary>
/// Registers a <see cref="ILogsWriter"/> with the default <see cref="CVLoggerProvider"/>.
/// </summary>
/// <typeparam name="TLogsWriter">Implementation of <see cref="ILogsWriter"/>.</typeparam>
/// <param name="serviceManager"><see cref="IServiceProducer"/>.</param>
/// <returns>Provided <see cref="IServiceProducer"/>.</returns>
public static IServiceProducer RegisterLogWriter<TLogsWriter>(this IServiceProducer serviceManager)
where TLogsWriter : ILogsWriter
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterSingleton<ILogsWriter, TLogsWriter>();
serviceManager.RegisterScoped<ILoggerFactory, LoggerFactory>(sp =>
{
var factory = new LoggerFactory();
factory.AddProvider(new CVLoggerProvider(sp.GetService<ILogsWriter>()));
return factory;
});
return serviceManager;
}
/// <summary>
/// Registers a <see cref="ILogsWriter"/> with the default <see cref="CVLoggerProvider"/>.
/// </summary>
/// <typeparam name="TILogsWriter">Interface of <see cref="ILogsWriter"/>.</typeparam>
/// <typeparam name="TLogsWriter">Implementation of <see cref="ILogsWriter"/>.</typeparam>
/// <param name="serviceManager"><see cref="IServiceProducer"/>.</param>
/// <returns>Provided <see cref="IServiceProducer"/>.</returns>
public static IServiceProducer RegisterLogWriter<TILogsWriter, TLogsWriter>(this IServiceProducer serviceManager)
where TLogsWriter : TILogsWriter
where TILogsWriter : class, ILogsWriter
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterSingleton<TILogsWriter, TLogsWriter>();
serviceManager.RegisterScoped<ILoggerFactory, LoggerFactory>(sp =>
{
var factory = new LoggerFactory();
factory.AddProvider(new CVLoggerProvider(sp.GetService<TILogsWriter>()));
return factory;
});
return serviceManager;
}
public static IServiceManager RegisterLoggerFactory(this IServiceManager serviceManager, Func<Slim.IServiceProvider, ILoggerFactory> loggerFactory)
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterSingleton<ILoggerFactory, ILoggerFactory>(loggerFactory);
return serviceManager;
}
public static IServiceManager RegisterDebugLoggerFactory(this IServiceManager serviceManager)
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterLogWriter<ILogsWriter, DebugLogsWriter>();
return serviceManager;
}
public static IServiceManager RegisterHttpFactory(this IServiceManager serviceManager)
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterResolver(new HttpClientResolver());
return serviceManager;
}
public static IServiceManager RegisterHttpFactory(this IServiceManager serviceManager, Func<Slim.IServiceProvider, Type, HttpMessageHandler> handlerFactory)
{
serviceManager.ThrowIfNull(nameof(serviceManager));
serviceManager.RegisterResolver(
new HttpClientResolver()
.WithHttpMessageHandlerFactory(handlerFactory));
return serviceManager;
}
}
}
@@ -0,0 +1,47 @@
using Slim.Resolvers;
using System.Linq;
using System.Net.Http;
namespace System.Http
{
public sealed class HttpClientResolver : IDependencyResolver
{
private static readonly Type clientType = typeof(HttpClient<>);
/// <summary>
/// Factory method. <see cref="Type"/> parameter of the factory is the scope of <see cref="IHttpClient{TScope}"/>.
/// </summary>
public Func<Slim.IServiceProvider, Type, HttpMessageHandler> HttpMessageHandlerFactory { get; set; }
/// <summary>
/// Sets the <see cref="HttpMessageHandlerFactory"/>.
/// </summary>
/// <param name="factory">Factory method. <see cref="Type"/> parameter of the factory is the scope of <see cref="IHttpClient{TScope}"/>.</param>
/// <returns></returns>
public HttpClientResolver WithHttpMessageHandlerFactory(Func<Slim.IServiceProvider, Type, HttpMessageHandler> factory)
{
this.HttpMessageHandlerFactory = factory;
return this;
}
public bool CanResolve(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IHttpClient<>))
{
return true;
}
return false;
}
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
{
var typedClientType = clientType.MakeGenericType(type.GetGenericArguments());
var handler = this.HttpMessageHandlerFactory?.Invoke(serviceProvider, type.GetGenericArguments().First());
var httpClient = handler is null ?
Activator.CreateInstance(typedClientType) :
Activator.CreateInstance(typedClientType, new object[] { handler });
return httpClient;
}
}
}
@@ -0,0 +1,44 @@
using Microsoft.Extensions.Logging;
using System.Extensions;
namespace System.Logging
{
public sealed class CVLogger : ILogger
{
private readonly string category;
private readonly ICVLoggerProvider cvLoggerProvider;
public CVLogger(string category, ICVLoggerProvider cvLoggerProvider)
{
this.category = category;
this.cvLoggerProvider = cvLoggerProvider.ThrowIfNull(nameof(cvLoggerProvider));
}
public IDisposable BeginScope<TState>(TState state)
{
return null;
}
public bool IsEnabled(LogLevel logLevel)
{
return true;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
var message = formatter(state, exception);
var log = new Log
{
Exception = exception,
LogLevel = logLevel,
EventId = eventId.Name,
Message = message,
Category = category,
LogTime = DateTime.Now
};
this.cvLoggerProvider.LogEntry(log);
}
}
}
@@ -0,0 +1,44 @@
using Microsoft.CorrelationVector;
using Microsoft.Extensions.Logging;
using System.Extensions;
namespace System.Logging
{
public sealed class CVLoggerProvider : ICVLoggerProvider
{
private readonly ILogsWriter logsManager;
private CorrelationVector correlationVector;
public CVLoggerProvider(ILogsWriter logsWriter)
{
this.logsManager = logsWriter.ThrowIfNull(nameof(logsWriter));
this.correlationVector = new CorrelationVector();
}
public void LogEntry(Log log)
{
if (this.correlationVector is not null)
{
log.CorrelationVector = this.correlationVector.Value.ToString();
this.correlationVector.Increment();
}
this.logsManager.WriteLog(log);
}
public ILogger CreateLogger(string categoryName)
{
if (this.correlationVector is not null)
{
this.correlationVector = CorrelationVector.Extend(this.correlationVector.ToString());
}
return new CVLogger(categoryName, this);
}
public void Dispose()
{
throw new System.NotImplementedException();
}
}
}
@@ -0,0 +1,12 @@
using System.Diagnostics;
namespace System.Logging
{
public sealed class DebugLogsWriter : ILogsWriter
{
public void WriteLog(Log log)
{
Debug.WriteLine($"{log.LogTime} - {log.Category} - {log.EventId} - {log.CorrelationVector} - {log.LogLevel} - {log.Message}{Environment.NewLine}{log.Exception}");
}
}
}
@@ -0,0 +1,9 @@
using Microsoft.Extensions.Logging;
namespace System.Logging
{
public interface ICVLoggerProvider : ILoggerProvider
{
void LogEntry(Log log);
}
}
@@ -0,0 +1,7 @@
namespace System.Logging
{
public interface ILogsWriter
{
void WriteLog(Log log);
}
}
@@ -0,0 +1,50 @@
using Microsoft.Extensions.Logging;
using Slim.Resolvers;
using System.Linq;
namespace System.Windows.Extensions.Logging
{
public sealed class LoggerResolver : IDependencyResolver
{
public bool CanResolve(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ILogger<>) ||
type == typeof(ILogger))
{
return true;
}
return false;
}
public object Resolve(Slim.IServiceProvider serviceProvider, Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ILogger<>))
{
return ResolveScopedLogger(serviceProvider, type);
}
else if (type == typeof(ILogger))
{
return ResolveLogger(serviceProvider, type);
}
else
{
throw new InvalidOperationException($"{nameof(LoggerResolver)} cannot resolve an object of type {type.Name}");
}
}
private static object ResolveScopedLogger(Slim.IServiceProvider serviceProvider, Type type)
{
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
var categoryTypes = type.GetGenericArguments();
var createLoggerMethod = typeof(LoggerFactoryExtensions).GetMethods().Where(m => m.IsGenericMethodDefinition && m.Name == nameof(LoggerFactoryExtensions.CreateLogger)).First();
return createLoggerMethod.MakeGenericMethod(categoryTypes.First()).Invoke(null, new object[] { loggerFactory });
}
private static object ResolveLogger(Slim.IServiceProvider serviceProvider, Type type)
{
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
return loggerFactory.CreateLogger(string.Empty);
}
}
}
@@ -0,0 +1,15 @@
using Microsoft.Extensions.Logging;
namespace System.Logging
{
public sealed record Log
{
public Exception Exception { get; set; }
public DateTime LogTime { get; set; }
public string Category { get; set; }
public string EventId { get; set; }
public LogLevel LogLevel { get; set; }
public string Message { get; set; }
public string CorrelationVector { get; set; }
}
}
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>System.DependencyInjection</RootNamespace>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<LangVersion>latest</LangVersion>
<Version>1.0.0</Version>
<Authors>Alexandru Macocian</Authors>
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<None Include="..\LICENSE" Link="LICENSE">
<PackagePath></PackagePath>
<Pack>True</Pack>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CorrelationVector" Version="1.0.42" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="Slim" Version="1.5.1" />
<PackageReference Include="SystemExtensions.NetStandard" Version="1.3.0" />
</ItemGroup>
</Project>
@@ -1,11 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// AVL tree implementation.
@@ -14,7 +9,7 @@ namespace SystemExtensions.Collections
/// </summary>
/// <typeparam name="T">Provided type.</typeparam>
[Serializable]
public class AVLTree<T> : ICollection<T> where T : IComparable<T>
public sealed class AVLTree<T> : ICollection<T> where T : IComparable<T>
{
#region Fields
[Serializable]
@@ -30,13 +25,14 @@ namespace SystemExtensions.Collections
}
AVLNode<T> root;
private int count = 0;
private bool isReadOnly = false;
private readonly bool isReadOnly = false;
#endregion
#region Properties
/// <summary>
/// Count of items currently stored in the tree.
/// </summary>
public int Count {
public int Count
{
get
{
return count;
@@ -51,7 +47,6 @@ namespace SystemExtensions.Collections
/// <summary>
/// Initializes a new instance of an AVLTree collection.
/// </summary>
/// <param name="comparator"></param>
public AVLTree()
{
@@ -83,7 +78,7 @@ namespace SystemExtensions.Collections
public bool Contains(T value)
{
AVLNode<T> node = Find(value, root);
if(node == null)
if (node == null)
{
return false;
}
@@ -113,16 +108,16 @@ namespace SystemExtensions.Collections
Queue<AVLNode<T>> queue = new Queue<AVLNode<T>>();
queue.Enqueue(root);
while(queue.Count > 0)
while (queue.Count > 0)
{
AVLNode<T> currentNode = queue.Dequeue();
if(currentNode.Left != null)
if (currentNode.Left != null)
{
queue.Enqueue(currentNode.Left);
currentNode.Left = null;
count--;
}
if(currentNode.Right != null)
if (currentNode.Right != null)
{
queue.Enqueue(currentNode.Right);
currentNode.Right = null;
@@ -293,7 +288,7 @@ namespace SystemExtensions.Collections
}
private AVLNode<T> Find(T target, AVLNode<T> current)
{
if(current == null)
if (current == null)
{
return null;
}
@@ -390,7 +385,5 @@ namespace SystemExtensions.Collections
}
}
#endregion
}
}
@@ -1,22 +1,19 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Binary heap implementation.
/// </summary>
/// <typeparam name="T">Provided type.</typeparam>
[Serializable]
public class BinaryHeap<T> : IEnumerable<T> where T : IComparable<T>
public sealed class BinaryHeap<T> : IEnumerable<T> where T : IComparable<T>
{
#region Fields
T[] items;
int capacity, count, initialCapacity;
private int capacity;
private int count;
private readonly int initialCapacity;
#endregion
#region Properties
/// <summary>
@@ -42,10 +39,12 @@ namespace SystemExtensions.Collections
/// <summary>
/// Capacity of the heap.
/// </summary>
public int Capacity { get => capacity;
public int Capacity
{
get => capacity;
set
{
if(value > capacity)
if (value > capacity)
{
Array.Resize(ref items, value);
capacity = value;
@@ -61,7 +60,6 @@ namespace SystemExtensions.Collections
/// <summary>
/// Constructor for a binary heap data structure.
/// </summary>
/// <param name="comparator">Function used to compare the elements.</param>
public BinaryHeap()
{
capacity = 10;
@@ -71,7 +69,6 @@ namespace SystemExtensions.Collections
/// <summary>
/// Constructor for a binary heap data structure.
/// </summary>
/// <param name="comparator">Function used to compare the elements.</param>
/// <param name="capacity">Initial capacity of the heap. Used for initial alocation of the array.</param>
public BinaryHeap(int capacity)
{
@@ -87,12 +84,12 @@ namespace SystemExtensions.Collections
/// <param name="value">Value to be added.</param>
public void Add(T value)
{
if(count == Capacity - 1)
if (count == Capacity - 1)
{
Capacity = 2 * Capacity;
}
int position = ++count;
for (; position > 1 && value.CompareTo(items[position / 2]) < 0; position = position / 2)
for (; position > 1 && value.CompareTo(items[position / 2]) < 0; position /= 2)
{
items[position] = items[position / 2];
}
@@ -159,8 +156,11 @@ namespace SystemExtensions.Collections
public void Clear(bool completeClear)
{
count = 0;
capacity = initialCapacity;
items = new T[initialCapacity];
if (completeClear)
{
capacity = initialCapacity;
items = new T[initialCapacity];
}
}
/// <summary>
/// Returns an enumerator that iterates over the heap.
@@ -168,7 +168,7 @@ namespace SystemExtensions.Collections
/// <returns>Enumerator that iterates over the heap.</returns>
public IEnumerator<T> GetEnumerator()
{
for(int i = 0; i < count; i++)
for (int i = 0; i < count; i++)
{
yield return items[i + 1];
}
@@ -182,15 +182,15 @@ namespace SystemExtensions.Collections
private void BubbleDown(int index)
{
T temp = items[index];
int childIndex = 0;
for(; 2*index <= count; index = childIndex)
int childIndex;
for (; 2 * index <= count; index = childIndex)
{
childIndex = 2 * index;
if(childIndex != Count && items[childIndex].CompareTo(items[childIndex + 1]) > 0)
if (childIndex != Count && items[childIndex].CompareTo(items[childIndex + 1]) > 0)
{
childIndex++;
}
if(temp.CompareTo(items[childIndex]) > 0)
if (temp.CompareTo(items[childIndex]) > 0)
{
items[index] = items[childIndex];
}
@@ -202,16 +202,6 @@ namespace SystemExtensions.Collections
items[index] = temp;
}
/// <summary>
/// Build heap from unordered array
/// </summary>
private void BuildHeap()
{
for(int i = count / 2; i > 0; i--)
{
BubbleDown(i);
}
}
/// <summary>
/// Implementation of IEnumerator.
/// </summary>
/// <returns>Enumerator over the array.</returns>
@@ -1,18 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Fibonacci Heap implementation.
/// </summary>
/// <typeparam name="T">Provided type</typeparam>
[Serializable]
public class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
public sealed class FibonacciHeap<T> : IEnumerable<T> where T : IComparable<T>
{
#region Fields
private FibonacciNode<T> root;
@@ -44,7 +37,6 @@ namespace SystemExtensions.Collections
/// <summary>
/// Constructor for Fibonacci heap data structure.
/// </summary>
/// <param name="comparator">Function used to compare the elements.</param>
public FibonacciHeap()
{
@@ -57,14 +49,16 @@ namespace SystemExtensions.Collections
/// <param name="value">Value to be added.</param>
public void Add(T value)
{
FibonacciNode<T> node = new FibonacciNode<T>();
node.Value = value;
FibonacciNode<T> node = new FibonacciNode<T>
{
Value = value,
Marked = false,
Child = null,
Parent = null,
Degree = 0
};
node.Previous = node.Next = node;
node.Degree = 0;
node.Marked = false;
node.Child = null;
node.Parent = null;
root = Merge(root, node);
root = this.Merge(root, node);
count++;
}
/// <summary>
@@ -131,7 +125,7 @@ namespace SystemExtensions.Collections
/// <returns>Array with values from the heap.</returns>
public T[] ToArray()
{
if(count == 0)
if (count == 0)
{
return null;
}
@@ -186,7 +180,7 @@ namespace SystemExtensions.Collections
{
Queue<FibonacciNode<T>> queue = new Queue<FibonacciNode<T>>();
queue.Enqueue(currentNode);
while(queue.Count > 0)
while (queue.Count > 0)
{
currentNode = queue.Dequeue();
FibonacciNode<T> oldNode = currentNode;
@@ -199,8 +193,8 @@ namespace SystemExtensions.Collections
}
currentNode = currentNode.Previous;
} while (currentNode != oldNode);
}
}
}
/// <summary>
/// Recursively remove the node and its children from the heap.
@@ -208,7 +202,7 @@ namespace SystemExtensions.Collections
/// <param name="node">Node to be removed.</param>
private void Remove(FibonacciNode<T> node)
{
if(node != null)
if (node != null)
{
FibonacciNode<T> current = node;
do
@@ -230,15 +224,15 @@ namespace SystemExtensions.Collections
/// <param name="node2">Root of second heap.</param>
private FibonacciNode<T> Merge(FibonacciNode<T> node1, FibonacciNode<T> node2)
{
if(node1 == null)
if (node1 == null)
{
return node2;
}
if(node2 == null)
if (node2 == null)
{
return node1;
}
if(node1.Value.CompareTo(node2.Value) > 0)
if (node1.Value.CompareTo(node2.Value) > 0)
{
FibonacciNode<T> temp = node1;
node1 = node2;
@@ -270,7 +264,7 @@ namespace SystemExtensions.Collections
/// <param name="node">Node to be removed from its parent.</param>
private void RemoveParent(FibonacciNode<T> node)
{
if(node == null)
if (node == null)
{
return;
}
@@ -290,7 +284,7 @@ namespace SystemExtensions.Collections
private FibonacciNode<T> RemoveMinimum(FibonacciNode<T> node)
{
RemoveParent(node.Child);
if(node.Next == node)
if (node.Next == node)
{
node = node.Child;
}
@@ -300,7 +294,7 @@ namespace SystemExtensions.Collections
node.Previous.Next = node.Next;
node = Merge(node.Next, node.Child);
}
if(node == null)
if (node == null)
{
return node;
}
@@ -308,15 +302,15 @@ namespace SystemExtensions.Collections
FibonacciNode<T>[] trees = new FibonacciNode<T>[64];
while (true)
{
if(trees[node.Degree] != null)
if (trees[node.Degree] != null)
{
FibonacciNode<T> t = trees[node.Degree];
if(t == node)
if (t == node)
{
break;
}
trees[node.Degree] = null;
if(node.Value.CompareTo(t.Value) < 0)
if (node.Value.CompareTo(t.Value) < 0)
{
t.Previous.Next = t.Next;
t.Next.Previous = t.Previous;
@@ -326,7 +320,7 @@ namespace SystemExtensions.Collections
{
t.Previous.Next = t.Next;
t.Next.Previous = t.Previous;
if(node.Next == node)
if (node.Next == node)
{
t.Next = t.Previous = t;
AddChild(t, node);
@@ -354,7 +348,7 @@ namespace SystemExtensions.Collections
FibonacciNode<T> start = node;
do
{
if(node.Value.CompareTo(min.Value) < 0)
if (node.Value.CompareTo(min.Value) < 0)
{
min = node;
}
@@ -370,7 +364,7 @@ namespace SystemExtensions.Collections
/// <returns></returns>
private FibonacciNode<T> Cut(FibonacciNode<T> root, FibonacciNode<T> node)
{
if(node.Next == node)
if (node.Next == node)
{
node.Parent.Child = null;
}
@@ -393,26 +387,26 @@ namespace SystemExtensions.Collections
/// <returns></returns>
private FibonacciNode<T> DecreaseKey(FibonacciNode<T> root, FibonacciNode<T> node, T value)
{
if(node.Value.CompareTo(value) < 0)
if (node.Value.CompareTo(value) < 0)
{
return root;
}
node.Value = value;
if(node.Parent != null)
if (node.Parent != null)
{
if(node.Value.CompareTo(node.Parent.Value) < 0)
if (node.Value.CompareTo(node.Parent.Value) < 0)
{
root = Cut(root, node);
FibonacciNode<T> parent = node.Parent;
node.Parent = null;
while(parent != null && parent.Marked)
while (parent != null && parent.Marked)
{
root = Cut(root, parent);
node = parent;
parent = node.Parent;
node.Parent = null;
}
if(parent != null && parent.Parent != null)
if (parent != null && parent.Parent != null)
{
parent.Marked = true;
}
@@ -420,7 +414,7 @@ namespace SystemExtensions.Collections
}
else
{
if(node.Value.CompareTo(root.Value) < 0)
if (node.Value.CompareTo(root.Value) < 0)
{
root = node;
}
@@ -436,18 +430,18 @@ namespace SystemExtensions.Collections
private FibonacciNode<T> Find(FibonacciNode<T> root, T value)
{
FibonacciNode<T> node = root;
if(node == null)
if (node == null)
{
return null;
}
do
{
if(node.Value.CompareTo(value) == 0)
if (node.Value.CompareTo(value) == 0)
{
return node;
}
FibonacciNode<T> ret = Find(node.Child, value);
if(ret != null)
if (ret != null)
{
return ret;
}
@@ -462,7 +456,7 @@ namespace SystemExtensions.Collections
#endregion
}
[Serializable]
internal class FibonacciNode<T>
internal sealed class FibonacciNode<T>
{
#region Fields
private FibonacciNode<T> previous;
@@ -537,7 +531,7 @@ namespace SystemExtensions.Collections
}
set
{
this.value = value;
this.value = value;
}
}
public int Degree
@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Interface for queue implementations.
@@ -1,11 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Priority Queue data structure. The implementation is based on an array-based implementation of Binary Heap.
@@ -13,10 +6,10 @@ namespace SystemExtensions.Collections
/// </summary>
/// <typeparam name="T">Provided type.</typeparam>
[Serializable]
public class PriorityQueue<T> : IQueue<T> where T : IComparable<T>
public sealed class PriorityQueue<T> : IQueue<T> where T : IComparable<T>
{
#region Fields
private BinaryHeap<T> binaryHeap;
private readonly BinaryHeap<T> binaryHeap;
#endregion
#region Properties
/// <summary>
@@ -34,7 +27,6 @@ namespace SystemExtensions.Collections
/// <summary>
/// Constructor for priority queue data structure.
/// </summary>
/// <param name="comparator">Function used to compare the elements.</param>
public PriorityQueue()
{
binaryHeap = new BinaryHeap<T>();
@@ -1,18 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Skip list implementation.
/// </summary>
/// <typeparam name="T">Provided type.</typeparam>
[Serializable]
public class SkipList<T> : ICollection<T> where T : IComparable<T>
public sealed class SkipList<T> : ICollection<T> where T : IComparable<T>
{
#region Fields
[Serializable]
@@ -30,10 +23,10 @@ namespace SystemExtensions.Collections
}
}
private int count;
private Random random;
private NodeSet<T> head;
private NodeSet<T> end;
private int maxLevel = 10;
private readonly Random random;
private readonly NodeSet<T> head;
private readonly NodeSet<T> end;
private readonly int maxLevel = 10;
private int level;
#endregion
#region Properties
@@ -53,11 +46,11 @@ namespace SystemExtensions.Collections
/// <param name="maxLevel">Maximum level of the skip list.</param>
public SkipList(int maxLevel = 10)
{
this.maxLevel = maxLevel;
this.maxLevel = maxLevel;
random = new Random();
head = new NodeSet<T>(default(T), maxLevel);
head = new NodeSet<T>(default, maxLevel);
end = head;
for(int i = 0; i <= maxLevel; i++)
for (int i = 0; i <= maxLevel; i++)
{
head.Next[i] = end;
}
@@ -84,7 +77,7 @@ namespace SystemExtensions.Collections
NodeSet<T> newNode = new NodeSet<T>(item, newLevel);
for (var i = 0; i <= newLevel; i++)
{
if(i > curNode.Level)
if (i > curNode.Level)
{
curNode = head;
}
@@ -108,7 +101,7 @@ namespace SystemExtensions.Collections
NodeSet<T> curNode = head;
for (var i = 0; i <= maxLevel; i++)
{
if(i > curNode.Level)
if (i > curNode.Level)
{
curNode = head;
}
@@ -141,7 +134,7 @@ namespace SystemExtensions.Collections
/// </summary>
public void Clear()
{
for(int i = 0; i < maxLevel; i++)
for (int i = 0; i < maxLevel; i++)
{
head.Next[i] = end;
}
@@ -154,7 +147,7 @@ namespace SystemExtensions.Collections
/// <returns>True if item is present in the collection.</returns>
public bool Contains(T item)
{
if(Find(item) != null)
if (Find(item) != null)
{
return true;
}
@@ -168,7 +161,7 @@ namespace SystemExtensions.Collections
public void CopyTo(T[] array, int arrayIndex)
{
NodeSet<T> node = head.Next[0];
while(node != end)
while (node != end)
{
array[arrayIndex] = node.Key;
arrayIndex++;
@@ -184,7 +177,7 @@ namespace SystemExtensions.Collections
T[] array = new T[count];
int index = 0;
NodeSet<T> curNode = head.Next[0];
while(curNode != end)
while (curNode != end)
{
array[index] = curNode.Key;
index++;
@@ -199,7 +192,7 @@ namespace SystemExtensions.Collections
public IEnumerator<T> GetEnumerator()
{
NodeSet<T> curNode = head.Next[0];
while(curNode != end)
while (curNode != end)
{
yield return curNode.Key;
curNode = curNode.Next[0];
@@ -215,15 +208,15 @@ namespace SystemExtensions.Collections
{
NodeSet<T> curNode = head;
for(int i = level; i >= 0; i--)
for (int i = level; i >= 0; i--)
{
while(curNode.Next[i] != end)
while (curNode.Next[i] != end)
{
if(curNode.Next[i].Key.CompareTo(key) > 0)
if (curNode.Next[i].Key.CompareTo(key) > 0)
{
break;
}
else if(curNode.Next[i].Key.CompareTo(key) == 0)
else if (curNode.Next[i].Key.CompareTo(key) == 0)
{
return curNode.Next[i];
}
@@ -232,7 +225,7 @@ namespace SystemExtensions.Collections
}
curNode = curNode.Next[0];
if(curNode != end && curNode.Key.CompareTo(key) == 0)
if (curNode != end && curNode.Key.CompareTo(key) == 0)
{
return curNode;
}
@@ -1,18 +1,11 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemExtensions.Collections
namespace System.Collections.Generic
{
/// <summary>
/// Treap implementation.
/// </summary>
/// <typeparam name="T">Provided type.</typeparam>
[Serializable]
public class Treap<T> : ICollection<T> where T : IComparable<T>
public sealed class Treap<T> : ICollection<T> where T : IComparable<T>
{
#region Fields
[Serializable]
@@ -29,7 +22,7 @@ namespace SystemExtensions.Collections
Right = null;
}
}
private Random randomGen;
private readonly Random randomGen;
private Node<T> root;
private int count;
#endregion
@@ -44,14 +37,15 @@ namespace SystemExtensions.Collections
return count;
}
}
public bool IsReadOnly => throw new NotImplementedException();
/// <summary>
/// Not implemented.
/// </summary>
public bool IsReadOnly => false;
#endregion
#region Constructors
/// <summary>
/// Constructor for treap.
/// </summary>
/// <param name="comparator">Comparator method used to compare values.</param>
public Treap()
{
randomGen = new Random();
@@ -134,14 +128,15 @@ namespace SystemExtensions.Collections
#region Private Methods
private Node<T> InsertNode(Node<T> node, T key)
{
if(node == null) {
if (node == null)
{
node = new Node<T>(key, randomGen.Next(0, 100));
return node;
}
else if (key.CompareTo(node.Key) <= 0)
{
node.Left = InsertNode(node.Left, key);
if(node.Left.Priority > node.Priority)
if (node.Left.Priority > node.Priority)
{
node = RotateRight(node);
}
@@ -149,7 +144,7 @@ namespace SystemExtensions.Collections
else
{
node.Right = InsertNode(node.Right, key);
if(node.Right.Priority > node.Priority)
if (node.Right.Priority > node.Priority)
{
node = RotateLeft(node);
}
@@ -158,27 +153,27 @@ namespace SystemExtensions.Collections
}
private Node<T> RemoveNode(Node<T> node, T key)
{
if(node == null)
if (node == null)
{
return node;
return node;
}
if(key.CompareTo(node.Key) < 0)
if (key.CompareTo(node.Key) < 0)
{
node.Left = RemoveNode(node.Left, key);
}
else if(key.CompareTo(node.Key) > 0)
else if (key.CompareTo(node.Key) > 0)
{
node.Right = RemoveNode(node.Right, key);
}
}
else if (node.Left == null)
{
node = node.Right;
}
else if(node.Right == null)
else if (node.Right == null)
{
node = node.Left;
}
else if(node.Left.Priority < node.Right.Priority)
else if (node.Left.Priority < node.Right.Priority)
{
node = RotateLeft(node);
node.Left = RemoveNode(node.Left, key);
@@ -206,11 +201,11 @@ namespace SystemExtensions.Collections
}
private void Clear(Node<T> node)
{
if(node.Left != null)
if (node.Left != null)
{
Clear(node.Left);
}
if(node.Right != null)
if (node.Right != null)
{
Clear(node.Right);
}
@@ -218,22 +213,22 @@ namespace SystemExtensions.Collections
}
private Node<T> Find(Node<T> node, T key)
{
if(node == null)
if (node == null)
{
return node;
}
else
{
if(node.Key.CompareTo(key) < 0)
if (node.Key.CompareTo(key) < 0)
{
Node<T> found = Find(node.Left, key);
if(found == null)
if (found == null)
{
found = Find(node.Right, key);
}
return found;
}
else if(node.Key.CompareTo(key) > 0)
else if (node.Key.CompareTo(key) > 0)
{
Node<T> found = Find(node.Right, key);
if (found == null)
@@ -250,7 +245,7 @@ namespace SystemExtensions.Collections
}
private void ToArray(Node<T> node, ref T[] array, ref int index)
{
if(node != null)
if (node != null)
{
ToArray(node.Left, ref array, ref index);
array[index] = node.Key;
@@ -262,15 +257,15 @@ namespace SystemExtensions.Collections
{
Queue<Node<T>> queue = new Queue<Node<T>>();
queue.Enqueue(currentNode);
while(queue.Count > 0)
while (queue.Count > 0)
{
currentNode = queue.Dequeue();
yield return currentNode.Key;
if(currentNode.Left != null)
if (currentNode.Left != null)
{
queue.Enqueue(currentNode.Left);
}
if(currentNode.Right != null)
if (currentNode.Right != null)
{
queue.Enqueue(currentNode.Right);
}
@@ -0,0 +1,24 @@
using System.IO;
namespace System.Extensions
{
public static class BytesExtensions
{
public static byte[] ReadAllBytes(this Stream stream)
{
if (stream is null) throw new ArgumentNullException(nameof(stream));
var buffer = new byte[256];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = stream.Read(buffer, 0, 256)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
}
}
@@ -0,0 +1,50 @@
namespace System.Extensions
{
public static class CastExtensions
{
public static int Floor(this double value)
{
return (int)Math.Floor(value);
}
public static int Ceiling(this double value)
{
return (int)Math.Ceiling(value);
}
public static int Round(this double value)
{
return (int)Math.Round(value);
}
public static int Floor(this float value)
{
return (int)Math.Floor(value);
}
public static int Ceiling(this float value)
{
return (int)Math.Ceiling(value);
}
public static int Round(this float value)
{
return (int)Math.Round(value);
}
public static int ToInt(this double value)
{
return (int)value;
}
public static int ToInt(this float value)
{
return (int)value;
}
public static int ToInt(this decimal value)
{
return (int)value;
}
}
}
@@ -0,0 +1,71 @@
using System.Collections.Generic;
using System.Linq;
namespace System.Extensions
{
public static class LinqExtensions
{
public static bool None<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
{
enumerable.ThrowIfNull(nameof(enumerable));
predicate.ThrowIfNull(nameof(predicate));
return !enumerable.Any(predicate);
}
public static bool None<T>(this IEnumerable<T> enumerable)
{
enumerable.ThrowIfNull(nameof(enumerable));
return !enumerable.Any();
}
public static ICollection<T> ClearAnd<T>(this ICollection<T> collection)
{
if (collection is null) throw new ArgumentNullException(nameof(collection));
collection.Clear();
return collection;
}
public static ICollection<T> AddRange<T>(this ICollection<T> collection, IEnumerable<T> values)
{
if (collection is null) throw new ArgumentNullException(nameof(collection));
if (values is null) throw new ArgumentNullException(nameof(values));
foreach(var item in values)
{
collection.Add(item);
}
return collection;
}
public static int IndexOfWhere<T>(this ICollection<T> collection, Func<T, bool> selector)
{
if (collection is null) throw new ArgumentNullException(nameof(collection));
if (selector is null) throw new ArgumentNullException(nameof(selector));
var index = 0;
foreach (var item in collection)
{
if (selector(item))
{
return index;
}
index++;
}
return -1;
}
public static IEnumerable<T> Do<T>(this IEnumerable<T> enumerable, Action<T> action)
{
foreach(var value in enumerable)
{
action(value);
yield return value;
}
}
}
}
@@ -0,0 +1,32 @@
namespace System.Extensions
{
public static class ObjectExtensions
{
public static T Cast<T>(this object obj)
{
return (T)obj;
}
public static T As<T>(this object obj) where T : class
{
return obj as T;
}
public static Optional<T> ToOptional<T>(this T obj)
{
return Optional.FromValue(obj);
}
public static T ThrowIfNull<T>([ValidatedNotNull] this T obj, string name) where T : class
{
if (obj is null) throw new ArgumentNullException(name);
return obj;
}
[AttributeUsage(AttributeTargets.Parameter)]
sealed class ValidatedNotNullAttribute : Attribute
{
}
}
}
@@ -0,0 +1,178 @@
namespace System.Extensions
{
public static class Optional
{
public static Optional<T> None<T>()
{
return new Optional<T>.None();
}
public static Optional<T> FromValue<T>(T value)
{
if (value == null)
{
return new Optional<T>.None();
}
return new Optional<T>.Some(value);
}
}
public abstract class Optional<T> : IEquatable<Optional<T>>
{
public Optional(T value)
{
this.Value = value;
}
private T Value { get; }
public T ExtractValue()
{
if (this is None)
{
return default;
}
else
{
return Value;
}
}
public Optional<T> Do(Action<T> onSome, Action onNone)
{
if (onSome is null) throw new ArgumentNullException(nameof(onSome));
if (onNone is null) throw new ArgumentNullException(nameof(onNone));
if (this is Some)
{
onSome.Invoke(this.Value);
}
else
{
onNone.Invoke();
}
return this;
}
public Optional<T> DoAny(Action<T> onSome = null, Action onNone = null)
{
if (this is Some)
{
onSome?.Invoke(this.Value);
}
else
{
onNone?.Invoke();
}
return this;
}
public Optional<V> Switch<V>(Func<T, V> onSome, Func<V> onNone)
{
if (onSome is null) throw new ArgumentNullException($"{nameof(onSome)}");
if (onNone is null) throw new ArgumentNullException($"{nameof(onNone)}");
if (this is Some)
{
return Optional.FromValue(onSome.Invoke(this.Value));
}
else
{
return Optional.FromValue(onNone.Invoke());
}
}
public Optional<V> SwitchAny<V>(Func<T, V> onSome = null, Func<V> onNone = null)
{
if (this is Some)
{
return onSome != null ? Optional.FromValue(onSome.Invoke(this.Value)) : Optional.FromValue(default(V));
}
else
{
return onNone != null ? Optional.FromValue(onNone.Invoke()) : Optional.FromValue(default(V));
}
}
public override bool Equals(object obj)
{
if (obj is Optional<T>)
{
return this.Equals(obj);
}
return base.Equals(obj);
}
public bool Equals(Optional<T> other)
{
if (this is Some && other is Some)
{
return this.As<Some>().Equals(other.As<Some>());
}
return false;
}
public static implicit operator Optional<T>(T value)
{
return Optional.FromValue(value);
}
public override int GetHashCode()
{
return this.Value == null ? base.GetHashCode() : this.Value.GetHashCode();
}
internal class Some : Optional<T>, IEquatable<Some>
{
public Some(T value) : base(value)
{
}
public override bool Equals(object obj)
{
if (obj is Some)
{
return this.Equals(obj.As<Some>());
}
return base.Equals(obj);
}
public bool Equals(Some other)
{
if (other is None)
{
return false;
}
if (other is Some)
{
return this.Value.Equals(other.Value);
}
return false;
}
public static bool operator ==(Some left, Some right)
{
return left?.Equals(right) == true;
}
public static bool operator !=(Some left, Some right)
{
return left?.Equals(right) != true;
}
public override int GetHashCode()
{
return this.Value is object ? this.Value.GetHashCode() : this.As<object>().GetHashCode();
}
}
internal class None : Optional<T>
{
public None() : base(default)
{
}
}
}
}
@@ -0,0 +1,185 @@
namespace System.Extensions
{
public class Result<TSuccess, TFailure>
{
private readonly object value;
public Result(TSuccess successValue)
{
value = successValue;
}
public Result(TFailure failureValue)
{
value = failureValue;
}
public bool TryExtractSuccess(out TSuccess successValue)
{
if (value is TSuccess success)
{
successValue = success;
return true;
}
else
{
successValue = default;
return false;
}
}
public bool TryExtractFailure(out TFailure failureValue)
{
if (value is TFailure failure)
{
failureValue = failure;
return true;
}
else
{
failureValue = default;
return false;
}
}
public Result<TSuccess, TFailure> Do(Action onSuccess, Action onFailure)
{
if (onSuccess is null) throw new ArgumentNullException(nameof(onSuccess));
if (onFailure is null) throw new ArgumentNullException(nameof(onFailure));
if (value is TSuccess)
{
onSuccess.Invoke();
}
else if (value is TFailure)
{
onFailure.Invoke();
}
return this;
}
public Result<TSuccess, TFailure> DoAny(Action onSuccess = null, Action onFailure = null)
{
if (value is TSuccess)
{
onSuccess?.Invoke();
}
else if (value is TFailure)
{
onFailure?.Invoke();
}
return this;
}
public Result<TSuccess, TFailure> Do(Action<TSuccess> onSuccess, Action<TFailure> onFailure)
{
if (onSuccess is null) throw new ArgumentNullException(nameof(onSuccess));
if (onFailure is null) throw new ArgumentNullException(nameof(onFailure));
if (value is TSuccess success)
{
onSuccess.Invoke(success);
}
else if (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)
{
onSuccess?.Invoke(success);
}
else if (value is TFailure failure)
{
onFailure?.Invoke(failure);
}
return this;
}
public T Switch<T>(Func<TSuccess, T> onSuccess, Func<TFailure, T> onFailure)
{
if (onSuccess is null) throw new ArgumentNullException(nameof(onSuccess));
if (onFailure is null) throw new ArgumentNullException(nameof(onFailure));
if (value is TSuccess success)
{
return onSuccess.Invoke(success);
}
else if (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)}");
}
public T SwitchAny<T>(Func<TSuccess, T> onSuccess = null, Func<TFailure, T> onFailure = null)
{
if (value is TSuccess success)
{
return onSuccess is null ? default : onSuccess.Invoke(success);
}
else if (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)}");
}
public Result<V, K> Switch<V, K>(Func<TSuccess, V> onSuccess, Func<TFailure, K> onFailure)
{
if (onSuccess is null) throw new ArgumentNullException(nameof(onSuccess));
if (onFailure is null) throw new ArgumentNullException(nameof(onFailure));
if (value is TSuccess success)
{
return Result<V, K>.Success(onSuccess.Invoke(success));
}
else if (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)}");
}
public Result<V, K> SwitchAny<V, K>(Func<TSuccess, V> onSuccess, Func<TFailure, K> onFailure)
{
if (value is TSuccess success)
{
return Result<V, K>.Success(onSuccess is null ? default : onSuccess.Invoke(success));
}
else if (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)}");
}
public Optional<TSuccess> ToOptional()
{
if (value is TSuccess)
{
return Optional.FromValue(value.Cast<TSuccess>());
}
return Optional.None<TSuccess>();
}
public static implicit operator Result<TSuccess, TFailure>(TSuccess success)
{
return Success(success);
}
public static implicit operator Result<TSuccess, TFailure>(TFailure failure)
{
return Failure(failure);
}
public static Result<TSuccess, TFailure> Success(TSuccess value)
{
return new Result<TSuccess, TFailure>(value);
}
public static Result<TSuccess, TFailure> Failure(TFailure value)
{
return new Result<TSuccess, TFailure>(value);
}
}
}
@@ -0,0 +1,67 @@
using System.IO;
using System.Text;
namespace System.Extensions
{
public static class StreamExtensions
{
public static void DoWhileReading(this Stream stream, Action<int, byte[]> action, int bufferLength = 256)
{
if (stream is null) throw new ArgumentNullException(nameof(stream));
if (action is null) throw new ArgumentNullException(nameof(action));
var buffer = new byte[bufferLength];
var read = stream.Read(buffer, 0, bufferLength);
while(read > 0)
{
action(bufferLength, buffer);
read = stream.Read(buffer, 0, bufferLength);
}
}
public static byte[] ReadBytes(this Stream stream, int count)
{
if (stream is null) throw new ArgumentNullException(nameof(stream));
var buffer = new byte[count];
stream.Read(buffer, 0, count);
return buffer;
}
public static Stream Rewind(this Stream stream)
{
if (stream is null) throw new ArgumentNullException(nameof(stream));
if (!stream.CanSeek) throw new InvalidOperationException("Stream doesn't support rewinding");
stream.Seek(0, SeekOrigin.Begin);
return stream;
}
public static string ReadUntil(this StreamReader sr, string delim)
{
var sb = new StringBuilder();
bool found = false;
while (!found && !sr.EndOfStream)
{
for (int i = 0; i < delim.Length; i++)
{
char c = (char)sr.Read();
sb.Append(c);
if (c != delim[i])
break;
if (i == delim.Length - 1)
{
sb.Remove(sb.Length - delim.Length, delim.Length);
found = true;
}
}
}
return sb.ToString();
}
}
}
@@ -0,0 +1,27 @@
using System.Text;
namespace System.Extensions
{
public static class StringExtensions
{
public static bool IsNullOrEmpty(this string s)
{
return string.IsNullOrEmpty(s);
}
public static bool IsNullOrWhiteSpace(this string s)
{
return string.IsNullOrWhiteSpace(s);
}
public static byte[] GetBytes(this string s)
{
return Encoding.UTF8.GetBytes(s);
}
public static string GetString(this byte[] bytes)
{
return Encoding.UTF8.GetString(bytes);
}
}
}
@@ -0,0 +1,180 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace System.Extensions
{
public static class TaskExtensions
{
/// <summary>
/// Mark task as <see cref="TaskCreationOptions.LongRunning"/>.
/// </summary>
/// <typeparam name="T">Result type.</typeparam>
/// <param name="task">Task.</param>
/// <returns>The started <see cref="Task{TResult}"/></returns>
public static Task<T> LongRunning<T>(this Task<T> task)
{
return Task.Factory.StartNew(async () =>
{
return await task;
}, TaskCreationOptions.LongRunning).Unwrap();
}
/// <summary>
/// Mark task as <see cref="TaskCreationOptions.LongRunning"/>.
/// </summary>
/// <param name="task">Task.</param>
/// <returns>The started <see cref="Task"/></returns>
public static Task LongRunning(this Task task)
{
return Task.Factory.StartNew(async () =>
{
await task;
}, TaskCreationOptions.LongRunning).Unwrap();
}
/// <summary>
/// Execute action periodically and asynchronously.
/// </summary>
/// <param name="onTick">Action to be executed.</param>
/// <param name="dueTime">Time to pass before starting to execute.</param>
/// <param name="interval">Interval between procs.</param>
/// <param name="token">Cancellation token used to cancel the cycle.</param>
/// <returns></returns>
public static async Task RunPeriodicAsync(this Action onTick, TimeSpan dueTime, TimeSpan interval, CancellationToken token)
{
if (dueTime > TimeSpan.Zero)
await Task.Delay(dueTime, token).ConfigureAwait(false);
while (!token.IsCancellationRequested)
{
onTick?.Invoke();
if (interval > TimeSpan.Zero)
await Task.Delay(interval, token).ConfigureAwait(false);
}
}
/// <summary>
/// Execute's an async Task<T> method which has a void return value synchronously
/// </summary>
/// <param name="task">Task<T> method to execute</param>
public static void RunSync(this Func<Task> task)
{
var oldContext = SynchronizationContext.Current;
var synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
synch.Post(async _ =>
{
try
{
await task();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
}
/// <summary>
/// Execute's an async Task<T> method which has a T return type synchronously
/// </summary>
/// <typeparam name="T">Return Type</typeparam>
/// <param name="task">Task<T> method to execute</param>
/// <returns></returns>
public static T RunSync<T>(this Func<Task<T>> task)
{
var oldContext = SynchronizationContext.Current;
var synch = new ExclusiveSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(synch);
T ret = default(T);
synch.Post(async _ =>
{
try
{
ret = await task();
}
catch (Exception e)
{
synch.InnerException = e;
throw;
}
finally
{
synch.EndMessageLoop();
}
}, null);
synch.BeginMessageLoop();
SynchronizationContext.SetSynchronizationContext(oldContext);
return ret;
}
private class ExclusiveSynchronizationContext : SynchronizationContext
{
private bool done;
public Exception InnerException { get; set; }
readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false);
readonly Queue<Tuple<SendOrPostCallback, object>> items =
new Queue<Tuple<SendOrPostCallback, object>>();
public override void Send(SendOrPostCallback d, object state)
{
throw new NotSupportedException("We cannot send to our same thread");
}
public override void Post(SendOrPostCallback d, object state)
{
lock (items)
{
items.Enqueue(Tuple.Create(d, state));
}
workItemsWaiting.Set();
}
public void EndMessageLoop()
{
Post(_ => done = true, null);
}
public void BeginMessageLoop()
{
while (!done)
{
Tuple<SendOrPostCallback, object> task = null;
lock (items)
{
if (items.Count > 0)
{
task = items.Dequeue();
}
}
if (task != null)
{
task.Item1(task.Item2);
if (InnerException != null) // the method threw an exeption
{
throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
}
}
else
{
workItemsWaiting.WaitOne();
}
}
}
public override SynchronizationContext CreateCopy()
{
return this;
}
}
}
}
@@ -0,0 +1,69 @@
using System.Collections.Generic;
namespace System.Extensions
{
public static class Try
{
public static Try<TResult> Action<TResult>(Func<TResult> act)
{
return new Try<TResult>(act);
}
}
public class Try<TResult>
{
private readonly Func<TResult> action;
private readonly List<Func<Exception, TResult>> catchActions = new List<Func<Exception, TResult>>();
internal Try(Func<TResult> action)
{
this.action = action;
}
public static Try<TResult> Action(Func<TResult> act)
{
return new Try<TResult>(act);
}
public Try<TResult> Catch<TException>(Func<TException, TResult> act) where TException : Exception
{
this.catchActions.Add((Func<Exception, TResult>)act);
return this;
}
public TResult Run()
{
try
{
return action();
}
catch (Exception ex)
{
foreach (var catchAction in this.catchActions)
{
return catchAction(ex);
}
throw;
}
}
public TResult Finally(Action act)
{
if (act is null) throw new ArgumentNullException(nameof(act));
try
{
return this.action();
}
catch (Exception ex)
{
foreach (var catchAction in this.catchActions)
{
return catchAction(ex);
}
throw;
}
finally
{
act();
}
}
}
}
@@ -0,0 +1,217 @@
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
namespace System.Http
{
public sealed class HttpClient<Tscope> : IHttpClient<Tscope>, IDisposable
{
private readonly HttpClient httpClient;
private readonly Type scope;
private EventHandler<HttpClientEventMessage> eventEmitted;
public event EventHandler<HttpClientEventMessage> EventEmitted
{
add
{
this.eventEmitted += value;
}
remove
{
this.eventEmitted -= value;
}
}
public Uri BaseAddress { get => this.httpClient.BaseAddress; set => this.httpClient.BaseAddress = value; }
public HttpRequestHeaders DefaultRequestHeaders => this.httpClient.DefaultRequestHeaders;
public long MaxResponseContentBufferSize { get => this.httpClient.MaxResponseContentBufferSize; set => this.httpClient.MaxResponseContentBufferSize = value; }
public TimeSpan Timeout { get => this.httpClient.Timeout; set => this.httpClient.Timeout = value; }
public HttpClient()
{
this.httpClient = new HttpClient();
this.scope = typeof(Tscope);
}
public HttpClient(
HttpMessageHandler handler)
{
this.httpClient = new HttpClient(handler);
this.scope = typeof(Tscope);
}
public HttpClient(
HttpMessageHandler handler,
bool disposeHandler)
{
this.httpClient = new HttpClient(handler, disposeHandler);
this.scope = typeof(Tscope);
}
public void CancelPendingRequests()
{
this.LogInformation(string.Empty, "Canceling request");
this.httpClient.CancelPendingRequests();
}
public Task<HttpResponseMessage> DeleteAsync(string requestUri)
{
this.LogInformation(requestUri, nameof(DeleteAsync));
return this.httpClient.DeleteAsync(requestUri);
}
public Task<HttpResponseMessage> DeleteAsync(string requestUri, CancellationToken cancellationToken)
{
this.LogInformation(requestUri, nameof(DeleteAsync));
return this.httpClient.DeleteAsync(requestUri, cancellationToken);
}
public Task<HttpResponseMessage> DeleteAsync(Uri requestUri)
{
this.LogInformation(requestUri.ToString(), nameof(DeleteAsync));
return this.httpClient.DeleteAsync(requestUri);
}
public Task<HttpResponseMessage> DeleteAsync(Uri requestUri, CancellationToken cancellationToken)
{
this.LogInformation(requestUri.ToString(), nameof(DeleteAsync));
return this.httpClient.DeleteAsync(requestUri, cancellationToken);
}
public Task<HttpResponseMessage> GetAsync(string requestUri)
{
this.LogInformation(requestUri, nameof(GetAsync));
return this.httpClient.GetAsync(requestUri);
}
public Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption)
{
this.LogInformation(requestUri, nameof(GetAsync));
return this.httpClient.GetAsync(requestUri, completionOption);
}
public Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
this.LogInformation(requestUri, nameof(GetAsync));
return this.httpClient.GetAsync(requestUri, completionOption, cancellationToken);
}
public Task<HttpResponseMessage> GetAsync(string requestUri, CancellationToken cancellationToken)
{
this.LogInformation(requestUri, nameof(GetAsync));
return this.httpClient.GetAsync(requestUri, cancellationToken);
}
public Task<HttpResponseMessage> GetAsync(Uri requestUri)
{
this.LogInformation(requestUri.ToString(), nameof(GetAsync));
return this.httpClient.GetAsync(requestUri);
}
public Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption)
{
this.LogInformation(requestUri.ToString(), nameof(GetAsync));
return this.httpClient.GetAsync(requestUri, completionOption);
}
public Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
this.LogInformation(requestUri.ToString(), nameof(GetAsync));
return this.httpClient.GetAsync(requestUri, completionOption, cancellationToken);
}
public Task<HttpResponseMessage> GetAsync(Uri requestUri, CancellationToken cancellationToken)
{
this.LogInformation(requestUri.ToString(), nameof(GetAsync));
return this.httpClient.GetAsync(requestUri, cancellationToken);
}
public Task<byte[]> GetByteArrayAsync(string requestUri)
{
this.LogInformation(requestUri, nameof(GetByteArrayAsync));
return this.httpClient.GetByteArrayAsync(requestUri);
}
public Task<byte[]> GetByteArrayAsync(Uri requestUri)
{
this.LogInformation(requestUri.ToString(), nameof(GetByteArrayAsync));
return this.httpClient.GetByteArrayAsync(requestUri);
}
public Task<Stream> GetStreamAsync(string requestUri)
{
this.LogInformation(requestUri, nameof(GetStreamAsync));
return this.httpClient.GetStreamAsync(requestUri);
}
public Task<Stream> GetStreamAsync(Uri requestUri)
{
this.LogInformation(requestUri.ToString(), nameof(GetStreamAsync));
return this.httpClient.GetStreamAsync(requestUri);
}
public Task<string> GetStringAsync(string requestUri)
{
this.LogInformation(requestUri, nameof(GetStringAsync));
return this.httpClient.GetStringAsync(requestUri);
}
public Task<string> GetStringAsync(Uri requestUri)
{
this.LogInformation(requestUri.ToString(), nameof(GetStringAsync));
return this.httpClient.GetStringAsync(requestUri);
}
public Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content)
{
this.LogInformation(requestUri, nameof(PostAsync));
return this.httpClient.PostAsync(requestUri, content);
}
public Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content, CancellationToken cancellationToken)
{
this.LogInformation(requestUri, nameof(PostAsync));
return this.httpClient.PostAsync(requestUri, content, cancellationToken);
}
public Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content)
{
this.LogInformation(requestUri.ToString(), nameof(PostAsync));
return this.httpClient.PostAsync(requestUri, content);
}
public Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken)
{
this.LogInformation(requestUri.ToString(), nameof(PostAsync));
return this.httpClient.PostAsync(requestUri, content, cancellationToken);
}
public Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content)
{
this.LogInformation(requestUri, nameof(PutAsync));
return this.httpClient.PutAsync(requestUri, content);
}
public Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content, CancellationToken cancellationToken)
{
this.LogInformation(requestUri, nameof(PutAsync));
return this.httpClient.PutAsync(requestUri, content, cancellationToken);
}
public Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content)
{
this.LogInformation(requestUri.ToString(), nameof(PutAsync));
return this.httpClient.PutAsync(requestUri, content);
}
public Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken)
{
this.LogInformation(requestUri.ToString(), nameof(PutAsync));
return this.httpClient.PutAsync(requestUri, content, cancellationToken);
}
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
{
this.LogInformation(request.RequestUri.ToString(), nameof(SendAsync));
return this.httpClient.SendAsync(request);
}
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption)
{
this.LogInformation(request.RequestUri.ToString(), nameof(SendAsync));
return this.httpClient.SendAsync(request, completionOption);
}
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
this.LogInformation(request.RequestUri.ToString(), nameof(SendAsync));
return this.httpClient.SendAsync(request, completionOption, cancellationToken);
}
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
this.LogInformation(request.RequestUri.ToString(), nameof(SendAsync));
return this.httpClient.SendAsync(request, cancellationToken);
}
public void Dispose()
{
this.httpClient.Dispose();
}
private void LogInformation(string url, string method)
{
this.eventEmitted?.Invoke(this, new HttpClientEventMessage(this.scope, method, url));
}
}
}
@@ -0,0 +1,16 @@
namespace System.Http
{
public sealed class HttpClientEventMessage
{
public Type Scope { get; }
public string Method { get; }
public string Url { get; }
internal HttpClientEventMessage(Type scope, string method, string url)
{
this.Scope = scope;
this.Method = method;
this.Url = url;
}
}
}
@@ -0,0 +1,49 @@
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
namespace System.Http
{
public interface IHttpClient<TScope>
{
event EventHandler<HttpClientEventMessage> EventEmitted;
Uri BaseAddress { get; set; }
HttpRequestHeaders DefaultRequestHeaders { get; }
long MaxResponseContentBufferSize { get; set; }
TimeSpan Timeout { get; set; }
void CancelPendingRequests();
Task<HttpResponseMessage> DeleteAsync(string requestUri);
Task<HttpResponseMessage> DeleteAsync(string requestUri, CancellationToken cancellationToken);
Task<HttpResponseMessage> DeleteAsync(Uri requestUri);
Task<HttpResponseMessage> DeleteAsync(Uri requestUri, CancellationToken cancellationToken);
Task<HttpResponseMessage> GetAsync(string requestUri);
Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption);
Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken);
Task<HttpResponseMessage> GetAsync(string requestUri, CancellationToken cancellationToken);
Task<HttpResponseMessage> GetAsync(Uri requestUri);
Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption);
Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken);
Task<HttpResponseMessage> GetAsync(Uri requestUri, CancellationToken cancellationToken);
Task<byte[]> GetByteArrayAsync(string requestUri);
Task<byte[]> GetByteArrayAsync(Uri requestUri);
Task<Stream> GetStreamAsync(string requestUri);
Task<Stream> GetStreamAsync(Uri requestUri);
Task<string> GetStringAsync(string requestUri);
Task<string> GetStringAsync(Uri requestUri);
Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content);
Task<HttpResponseMessage> PostAsync(string requestUri, HttpContent content, CancellationToken cancellationToken);
Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content);
Task<HttpResponseMessage> PostAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken);
Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content);
Task<HttpResponseMessage> PutAsync(string requestUri, HttpContent content, CancellationToken cancellationToken);
Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content);
Task<HttpResponseMessage> PutAsync(Uri requestUri, HttpContent content, CancellationToken cancellationToken);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken);
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
}
}
@@ -0,0 +1,175 @@
namespace System.Structures.BitStructures
{
public struct Int32BitStruct : IEquatable<Int32BitStruct>
{
public Int32BitStruct(uint value) => this.Value = value;
public Int32BitStruct(int value) { unchecked { this.Value = (uint)value; } }
public uint Value { get; set; }
public uint Bit0 { get => this.Value & 0x1; set => this.Value = (this.Value & ~(0x1U) | (0x1 & value)); }
public uint Bit1 { get => this.Value >> 1 & 0x1; set => this.Value = (this.Value & ~(0x1U << 1)) | ((0x1 & value) << 1); }
public uint Bit2 { get => this.Value >> 2 & 0x1; set => this.Value = (this.Value & ~(0x1U << 2)) | ((0x1 & value) << 2); }
public uint Bit3 { get => this.Value >> 3 & 0x1; set => this.Value = (this.Value & ~(0x1U << 3)) | ((0x1 & value) << 3); }
public uint Bit4 { get => this.Value >> 4 & 0x1; set => this.Value = (this.Value & ~(0x1U << 4)) | ((0x1 & value) << 4); }
public uint Bit5 { get => this.Value >> 5 & 0x1; set => this.Value = (this.Value & ~(0x1U << 5)) | ((0x1 & value) << 5); }
public uint Bit6 { get => this.Value >> 6 & 0x1; set => this.Value = (this.Value & ~(0x1U << 6)) | ((0x1 & value) << 6); }
public uint Bit7 { get => this.Value >> 7 & 0x1; set => this.Value = (this.Value & ~(0x1U << 7)) | ((0x1 & value) << 7); }
public uint Bit8 { get => this.Value >> 8 & 0x1; set => this.Value = (this.Value & ~(0x1U << 8)) | ((0x1 & value) << 8); }
public uint Bit9 { get => this.Value >> 9 & 0x1; set => this.Value = (this.Value & ~(0x1U << 9)) | ((0x1 & value) << 9); }
public uint Bit10 { get => this.Value >> 10 & 0x1; set => this.Value = (this.Value & ~(0x1U << 10)) | ((0x1 & value) << 10); }
public uint Bit11 { get => this.Value >> 11 & 0x1; set => this.Value = (this.Value & ~(0x1U << 11)) | ((0x1 & value) << 11); }
public uint Bit12 { get => this.Value >> 12 & 0x1; set => this.Value = (this.Value & ~(0x1U << 12)) | ((0x1 & value) << 12); }
public uint Bit13 { get => this.Value >> 13 & 0x1; set => this.Value = (this.Value & ~(0x1U << 13)) | ((0x1 & value) << 13); }
public uint Bit14 { get => this.Value >> 14 & 0x1; set => this.Value = (this.Value & ~(0x1U << 14)) | ((0x1 & value) << 14); }
public uint Bit15 { get => this.Value >> 15 & 0x1; set => this.Value = (this.Value & ~(0x1U << 15)) | ((0x1 & value) << 15); }
public uint Bit16 { get => this.Value >> 16 & 0x1; set => this.Value = (this.Value & ~(0x1U << 16)) | ((0x1 & value) << 16); }
public uint Bit17 { get => this.Value >> 17 & 0x1; set => this.Value = (this.Value & ~(0x1U << 17)) | ((0x1 & value) << 17); }
public uint Bit18 { get => this.Value >> 18 & 0x1; set => this.Value = (this.Value & ~(0x1U << 18)) | ((0x1 & value) << 18); }
public uint Bit19 { get => this.Value >> 19 & 0x1; set => this.Value = (this.Value & ~(0x1U << 19)) | ((0x1 & value) << 19); }
public uint Bit20 { get => this.Value >> 20 & 0x1; set => this.Value = (this.Value & ~(0x1U << 20)) | ((0x1 & value) << 20); }
public uint Bit21 { get => this.Value >> 21 & 0x1; set => this.Value = (this.Value & ~(0x1U << 21)) | ((0x1 & value) << 21); }
public uint Bit22 { get => this.Value >> 22 & 0x1; set => this.Value = (this.Value & ~(0x1U << 22)) | ((0x1 & value) << 22); }
public uint Bit23 { get => this.Value >> 23 & 0x1; set => this.Value = (this.Value & ~(0x1U << 23)) | ((0x1 & value) << 23); }
public uint Bit24 { get => this.Value >> 24 & 0x1; set => this.Value = (this.Value & ~(0x1U << 24)) | ((0x1 & value) << 24); }
public uint Bit25 { get => this.Value >> 25 & 0x1; set => this.Value = (this.Value & ~(0x1U << 25)) | ((0x1 & value) << 25); }
public uint Bit26 { get => this.Value >> 26 & 0x1; set => this.Value = (this.Value & ~(0x1U << 26)) | ((0x1 & value) << 26); }
public uint Bit27 { get => this.Value >> 27 & 0x1; set => this.Value = (this.Value & ~(0x1U << 27)) | ((0x1 & value) << 27); }
public uint Bit28 { get => this.Value >> 28 & 0x1; set => this.Value = (this.Value & ~(0x1U << 28)) | ((0x1 & value) << 28); }
public uint Bit29 { get => this.Value >> 29 & 0x1; set => this.Value = (this.Value & ~(0x1U << 29)) | ((0x1 & value) << 29); }
public uint Bit30 { get => this.Value >> 30 & 0x1; set => this.Value = (this.Value & ~(0x1U << 30)) | ((0x1 & value) << 30); }
public uint Bit31 { get => this.Value >> 31 & 0x1; set => this.Value = (this.Value & ~(0x1U << 31)) | ((0x1 & value) << 31); }
public static implicit operator Int32BitStruct(uint value) => new Int32BitStruct(value);
public static implicit operator Int32BitStruct(int value) => new Int32BitStruct(value);
public static implicit operator int(Int32BitStruct value) => (int)value.Value;
public static implicit operator uint(Int32BitStruct value) => value.Value;
public static bool operator ==(Int32BitStruct first, Int32BitStruct second)
{
return first.Value == second.Value;
}
public static bool operator !=(Int32BitStruct first, Int32BitStruct second)
{
return first.Value != second.Value;
}
public static bool operator ==(Int32BitStruct first, uint second)
{
return first.Value == second;
}
public static bool operator !=(Int32BitStruct first, uint second)
{
return first.Value != second;
}
public static bool operator ==(Int32BitStruct first, int second)
{
unchecked
{
return first.Value == (uint)second;
}
}
public static bool operator !=(Int32BitStruct first, int second)
{
unchecked
{
return first.Value != (uint)second;
}
}
public static bool operator >=(Int32BitStruct first, Int32BitStruct second)
{
return first.Value >= second.Value;
}
public static bool operator <=(Int32BitStruct first, Int32BitStruct second)
{
return first.Value <= second.Value;
}
public static bool operator >=(Int32BitStruct first, int second)
{
unchecked
{
return first.Value >= (uint)second;
}
}
public static bool operator <=(Int32BitStruct first, int second)
{
unchecked
{
return first.Value <= (uint)second;
}
}
public static bool operator >=(Int32BitStruct first, uint second)
{
return first.Value >= second;
}
public static bool operator <=(Int32BitStruct first, uint second)
{
return first.Value <= second;
}
public static bool operator >(Int32BitStruct first, Int32BitStruct second)
{
return first.Value > second.Value;
}
public static bool operator <(Int32BitStruct first, Int32BitStruct second)
{
return first.Value < second.Value;
}
public static bool operator >(Int32BitStruct first, int second)
{
unchecked
{
return first.Value > (uint)second;
}
}
public static bool operator <(Int32BitStruct first, int second)
{
unchecked
{
return first.Value < (uint)second;
}
}
public static bool operator >(Int32BitStruct first, uint second)
{
return first.Value > second;
}
public static bool operator <(Int32BitStruct first, uint second)
{
return first.Value < second;
}
public bool Equals(Int32BitStruct other)
{
return this.Value == other.Value;
}
public override bool Equals(object obj)
{
if (obj is Int32BitStruct)
{
return this.Equals((Int32BitStruct)obj);
}
else
{
return base.Equals(obj);
}
}
public override int GetHashCode()
{
return (this.Value).GetHashCode();
}
}
}
@@ -0,0 +1,205 @@
using System;
namespace System.Structures.BitStructures
{
public struct Int64BitStruct : IEquatable<Int64BitStruct>
{
public Int64BitStruct(uint low, uint high)
{
this.Value = low + ((ulong)high << 32);
}
public Int64BitStruct(int low, int high)
{
unchecked
{
this.Value = (uint)low + ((ulong)high << 32);
}
}
public Int64BitStruct(long value)
{
unchecked
{
this.Value = (ulong)value;
}
}
public Int64BitStruct(ulong value)
{
this.Value = value;
}
public ulong Value { get; set; }
public uint Low { get => (uint)(this.Value & 0xFFFFFFFF); set => this.Value = (this.Value & ~(0xFFFFFFFF)) | (0xFFFFFFFF & value); }
public uint High { get => (uint)((this.Value >> 32) & 0xFFFFFFFF); set => this.Value = (this.Value & ~(0xFFFFFFFF00000000)) | ((ulong)(0xFFFFFFFF & value) << 32); }
public ulong Bit0 { get => this.Value & 0x1; set => this.Value = (this.Value & ~(0x1UL) | (0x1 & value)); }
public ulong Bit1 { get => this.Value >> 1 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 1)) | ((0x1 & value) << 1); }
public ulong Bit2 { get => this.Value >> 2 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 2)) | ((0x1 & value) << 2); }
public ulong Bit3 { get => this.Value >> 3 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 3)) | ((0x1 & value) << 3); }
public ulong Bit4 { get => this.Value >> 4 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 4)) | ((0x1 & value) << 4); }
public ulong Bit5 { get => this.Value >> 5 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 5)) | ((0x1 & value) << 5); }
public ulong Bit6 { get => this.Value >> 6 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 6)) | ((0x1 & value) << 6); }
public ulong Bit7 { get => this.Value >> 7 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 7)) | ((0x1 & value) << 7); }
public ulong Bit8 { get => this.Value >> 8 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 8)) | ((0x1 & value) << 8); }
public ulong Bit9 { get => this.Value >> 9 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 9)) | ((0x1 & value) << 9); }
public ulong Bit10 { get => this.Value >> 10 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 10)) | ((0x1 & value) << 10); }
public ulong Bit11 { get => this.Value >> 11 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 11)) | ((0x1 & value) << 11); }
public ulong Bit12 { get => this.Value >> 12 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 12)) | ((0x1 & value) << 12); }
public ulong Bit13 { get => this.Value >> 13 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 13)) | ((0x1 & value) << 13); }
public ulong Bit14 { get => this.Value >> 14 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 14)) | ((0x1 & value) << 14); }
public ulong Bit15 { get => this.Value >> 15 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 15)) | ((0x1 & value) << 15); }
public ulong Bit16 { get => this.Value >> 16 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 16)) | ((0x1 & value) << 16); }
public ulong Bit17 { get => this.Value >> 17 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 17)) | ((0x1 & value) << 17); }
public ulong Bit18 { get => this.Value >> 18 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 18)) | ((0x1 & value) << 18); }
public ulong Bit19 { get => this.Value >> 19 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 19)) | ((0x1 & value) << 19); }
public ulong Bit20 { get => this.Value >> 20 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 20)) | ((0x1 & value) << 20); }
public ulong Bit21 { get => this.Value >> 21 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 21)) | ((0x1 & value) << 21); }
public ulong Bit22 { get => this.Value >> 22 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 22)) | ((0x1 & value) << 22); }
public ulong Bit23 { get => this.Value >> 23 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 23)) | ((0x1 & value) << 23); }
public ulong Bit24 { get => this.Value >> 24 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 24)) | ((0x1 & value) << 24); }
public ulong Bit25 { get => this.Value >> 25 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 25)) | ((0x1 & value) << 25); }
public ulong Bit26 { get => this.Value >> 26 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 26)) | ((0x1 & value) << 26); }
public ulong Bit27 { get => this.Value >> 27 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 27)) | ((0x1 & value) << 27); }
public ulong Bit28 { get => this.Value >> 28 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 28)) | ((0x1 & value) << 28); }
public ulong Bit29 { get => this.Value >> 29 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 29)) | ((0x1 & value) << 29); }
public ulong Bit30 { get => this.Value >> 30 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 30)) | ((0x1 & value) << 30); }
public ulong Bit31 { get => this.Value >> 31 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 31)) | ((0x1 & value) << 31); }
public ulong Bit32 { get => this.Value >> 32 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 32)) | ((0x1 & value) << 32); }
public ulong Bit33 { get => this.Value >> 33 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 33)) | ((0x1 & value) << 33); }
public ulong Bit34 { get => this.Value >> 34 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 34)) | ((0x1 & value) << 34); }
public ulong Bit35 { get => this.Value >> 35 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 35)) | ((0x1 & value) << 35); }
public ulong Bit36 { get => this.Value >> 36 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 36)) | ((0x1 & value) << 36); }
public ulong Bit37 { get => this.Value >> 37 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 37)) | ((0x1 & value) << 37); }
public ulong Bit38 { get => this.Value >> 38 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 38)) | ((0x1 & value) << 38); }
public ulong Bit39 { get => this.Value >> 39 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 39)) | ((0x1 & value) << 39); }
public ulong Bit40 { get => this.Value >> 40 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 40)) | ((0x1 & value) << 40); }
public ulong Bit41 { get => this.Value >> 41 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 41)) | ((0x1 & value) << 41); }
public ulong Bit42 { get => this.Value >> 42 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 42)) | ((0x1 & value) << 42); }
public ulong Bit43 { get => this.Value >> 43 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 43)) | ((0x1 & value) << 43); }
public ulong Bit44 { get => this.Value >> 44 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 44)) | ((0x1 & value) << 44); }
public ulong Bit45 { get => this.Value >> 45 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 45)) | ((0x1 & value) << 45); }
public ulong Bit46 { get => this.Value >> 46 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 46)) | ((0x1 & value) << 46); }
public ulong Bit47 { get => this.Value >> 47 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 47)) | ((0x1 & value) << 47); }
public ulong Bit48 { get => this.Value >> 48 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 48)) | ((0x1 & value) << 48); }
public ulong Bit49 { get => this.Value >> 49 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 49)) | ((0x1 & value) << 49); }
public ulong Bit50 { get => this.Value >> 50 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 50)) | ((0x1 & value) << 50); }
public ulong Bit51 { get => this.Value >> 51 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 51)) | ((0x1 & value) << 51); }
public ulong Bit52 { get => this.Value >> 52 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 52)) | ((0x1 & value) << 52); }
public ulong Bit53 { get => this.Value >> 53 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 53)) | ((0x1 & value) << 53); }
public ulong Bit54 { get => this.Value >> 54 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 54)) | ((0x1 & value) << 54); }
public ulong Bit55 { get => this.Value >> 55 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 55)) | ((0x1 & value) << 55); }
public ulong Bit56 { get => this.Value >> 56 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 56)) | ((0x1 & value) << 56); }
public ulong Bit57 { get => this.Value >> 57 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 57)) | ((0x1 & value) << 57); }
public ulong Bit58 { get => this.Value >> 58 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 58)) | ((0x1 & value) << 58); }
public ulong Bit59 { get => this.Value >> 59 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 59)) | ((0x1 & value) << 59); }
public ulong Bit60 { get => this.Value >> 60 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 60)) | ((0x1 & value) << 60); }
public ulong Bit61 { get => this.Value >> 61 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 61)) | ((0x1 & value) << 61); }
public ulong Bit62 { get => this.Value >> 62 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 62)) | ((0x1 & value) << 62); }
public ulong Bit63 { get => this.Value >> 63 & 0x1; set => this.Value = (this.Value & ~(0x1UL << 63)) | ((0x1 & value) << 63); }
public static implicit operator Int64BitStruct(ulong value) => new Int64BitStruct(value);
public static implicit operator Int64BitStruct(long value) => new Int64BitStruct(value);
public static implicit operator long(Int64BitStruct value) => (long)value.Value;
public static implicit operator ulong(Int64BitStruct value) => value.Value;
public static bool operator ==(Int64BitStruct first, Int64BitStruct second)
{
return first.Value == second.Value;
}
public static bool operator !=(Int64BitStruct first, Int64BitStruct second)
{
return first.Value != second.Value;
}
public static bool operator ==(Int64BitStruct first, ulong second)
{
return first.Value == second;
}
public static bool operator !=(Int64BitStruct first, ulong second)
{
return first.Value != second;
}
public static bool operator ==(Int64BitStruct first, long second)
{
unchecked
{
return first.Value == (ulong)second;
}
}
public static bool operator !=(Int64BitStruct first, long second)
{
unchecked
{
return first.Value != (ulong)second;
}
}
public static bool operator >=(Int64BitStruct first, Int64BitStruct second)
{
return first.Value >= second.Value;
}
public static bool operator <=(Int64BitStruct first, Int64BitStruct second)
{
return first.Value <= second.Value;
}
public static bool operator >=(Int64BitStruct first, long second)
{
unchecked
{
return first.Value >= (ulong)second;
}
}
public static bool operator <=(Int64BitStruct first, long second)
{
unchecked
{
return first.Value <= (ulong)second;
}
}
public static bool operator >=(Int64BitStruct first, ulong second)
{
unchecked
{
return first.Value >= second;
}
}
public static bool operator <=(Int64BitStruct first, ulong second)
{
unchecked
{
return first.Value <= second;
}
}
public bool Equals(Int64BitStruct other)
{
return this.Value == other.Value;
}
public override bool Equals(object obj)
{
if (obj is Int64BitStruct)
{
return this.Equals((Int64BitStruct)obj);
}
else
{
return base.Equals(obj);
}
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
}
}
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<RootNamespace>System</RootNamespace>
<Version>1.3.0</Version>
<Authors>Alexandru Macocian</Authors>
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<None Include="../LICENSE">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>
</Project>
@@ -1,12 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SystemExtensions.Collections;
using System.Collections.Generic;
namespace SystemExtensions.Threading
namespace System.Threading
{
/// <summary>
/// Threadpool implementation that uses a priority queue as the queue for the tasks to execute.
@@ -17,9 +11,9 @@ namespace SystemExtensions.Threading
{
private class QueueEntry : IComparable<QueueEntry>
{
public TaskPriority TaskPriority;
public WaitCallback WaitCallback;
public Object Object;
public TaskPriority TaskPriority { get; }
public WaitCallback WaitCallback { get; }
public object Object { get; }
public QueueEntry(TaskPriority priority, WaitCallback callback, object obj)
{
this.TaskPriority = priority;
@@ -116,19 +110,22 @@ namespace SystemExtensions.Threading
private volatile List<WorkerThread> threadpool;
private volatile PriorityQueue<QueueEntry> tasks;
private Thread observer;
private CancellationTokenSource observerCancellationTokenSource = new CancellationTokenSource();
private int maxThreads;
private object tasksLock = new object();
private readonly object tasksLock = new object();
private struct WorkerThread
{
public Thread thread;
public bool running, working;
public Thread Thread { get; set; }
public bool Running { get; set; }
public bool Working { get; set; }
public CancellationTokenSource CancellationTokenSource { get; set; }
}
private struct Statistics
{
public bool Initialized;
public int PerformanceCounter;
public DateTime LastUpdate;
public double LoopFrequency;
public bool Initialized { get; set; }
public int PerformanceCounter { get; set; }
public DateTime LastUpdate { get; set; }
public double LoopFrequency { get; set; }
}
#endregion
#region Properties
@@ -139,7 +136,7 @@ namespace SystemExtensions.Threading
{
get
{
return threadpool.Count;
return this.threadpool is null ? 0 : this.threadpool.Count;
}
}
/// <summary>
@@ -149,7 +146,7 @@ namespace SystemExtensions.Threading
{
get
{
return tasks.Count == 0;
return this.tasks is null ? true : this.tasks.Count == 0;
}
}
/// <summary>
@@ -179,22 +176,13 @@ namespace SystemExtensions.Threading
maxThreads = System.Environment.ProcessorCount;
for (int i = 0; i < maxThreads; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread();
}
observer = new Thread(() =>
observer = new Thread(() => ObserverLoop())
{
ObserverLoop();
});
observer.Name = "ThreadPool ObserverThread";
observer.Priority = ThreadPriority.BelowNormal;
Name = "ThreadPool ObserverThread",
Priority = ThreadPriority.BelowNormal
};
observer.Start();
}
/// <summary>
@@ -208,20 +196,9 @@ namespace SystemExtensions.Threading
this.maxThreads = Math.Max(maxThreads, 1);
for (int i = 0; i < maxThreads; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread();
}
observer = new Thread(() =>
{
ObserverLoop();
});
observer = new Thread(() => ObserverLoop());
observer.Name = "ThreadPool ObserverThread";
observer.Priority = ThreadPriority.BelowNormal;
observer.Start();
@@ -239,72 +216,27 @@ namespace SystemExtensions.Threading
{
threadpool = new List<WorkerThread>();
tasks = new PriorityQueue<QueueEntry>();
for(int i = 0; i < lowest; i++)
for (int i = 0; i < lowest; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.thread.Priority = ThreadPriority.Lowest;
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread(ThreadPriority.Lowest);
}
for (int i = 0; i < belowNormal; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.thread.Priority = ThreadPriority.BelowNormal;
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread(ThreadPriority.BelowNormal);
}
for (int i = 0; i < normal; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.thread.Priority = ThreadPriority.Normal;
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread(ThreadPriority.Normal);
}
for (int i = 0; i < aboveNormal; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.thread.Priority = ThreadPriority.AboveNormal;
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread(ThreadPriority.AboveNormal);
}
for (int i = 0; i < highest; i++)
{
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.thread.Priority = ThreadPriority.Highest;
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread(ThreadPriority.Highest);
}
}
}
#endregion
#region Public Methods
/// <summary>
@@ -315,7 +247,7 @@ namespace SystemExtensions.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(tasksLock)) ;
tasks.Enqueue(new QueueEntry(taskPriority, waitCallback, callbackState));
Monitor.Exit(tasksLock);
}
@@ -330,24 +262,50 @@ namespace SystemExtensions.Threading
}
#endregion
#region Private Methods
private void CreateAndStartWorkerThread(ThreadPriority threadPriority)
{
var worker = new WorkerThread();
worker.Thread = new Thread(() => 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);
}
private void CreateAndStartWorkerThread()
{
var worker = new WorkerThread();
worker.Thread = new Thread(() => ThreadMainLoop(ref worker));
worker.Thread.Name = "ThreadPool WorkerThread";
worker.Running = true;
worker.CancellationTokenSource = new CancellationTokenSource();
worker.Thread.Start();
threadpool.Add(worker);
}
/// <summary>
/// Main loop that a thread from the pool is running.
/// </summary>
/// <threadId>Id of thread</threadId>
private void ThreadMainLoop(ref WorkerThread thisWorkerThread)
{
thisWorkerThread.running = true;
while (thisWorkerThread.running)
thisWorkerThread.Running = true;
while (thisWorkerThread.Running)
{
//Check if there are tasks
if (thisWorkerThread.CancellationTokenSource.Token.IsCancellationRequested)
{
thisWorkerThread.Running = false;
return;
}
//Check if there are tasks
if (tasks.Count > 0)
{
//If there are tasks, acquire a lock onto the list
//and try to dequeue the highest priority task.
//Finally, release the lock and invoke the task.
thisWorkerThread.working = true;
thisWorkerThread.Working = true;
QueueEntry task = null;
while (!Monitor.TryEnter(tasksLock)) ;
if (tasks.Count > 0)
@@ -361,7 +319,7 @@ namespace SystemExtensions.Threading
WaitCallback waitCallback = task.WaitCallback;
waitCallback.Invoke(task.Object);
}
thisWorkerThread.working = false;
thisWorkerThread.Working = false;
}
}
}
@@ -380,11 +338,16 @@ namespace SystemExtensions.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)
{
return;
}
//This part of code updates the statistics of the threadpool.
if (statistics.Initialized)
{
double loopDuration = (DateTime.Now - statistics.LastUpdate).TotalMilliseconds;
if(statistics.LoopFrequency == 0)
if (statistics.LoopFrequency == 0)
{
statistics.LoopFrequency = loopDuration;
}
@@ -403,10 +366,10 @@ namespace SystemExtensions.Threading
//This part of code adjusts the performance counter. Ideally, the value should be 0.
if(tasks.Count > 0)
if (tasks.Count > 0)
{
statistics.PerformanceCounter++;
if(statistics.PerformanceCounter > 5)
if (statistics.PerformanceCounter > 5)
{
statistics.PerformanceCounter = 5;
}
@@ -414,18 +377,18 @@ namespace SystemExtensions.Threading
else
{
statistics.PerformanceCounter--;
if(statistics.PerformanceCounter < -10)
if (statistics.PerformanceCounter < -10)
{
statistics.PerformanceCounter = -10;
}
}
//This part of code adjusts thread priorities based on the current performance of the threadpool
if(tasks.Count > 0)
if (tasks.Count > 0)
{
//If there are tasks pending, find a thread with priority under Normal and upgrade its priority.
Thread t = FindThreadWithLowPriority();
if(t != null)
if (t != null)
{
UpgradeThreadPriority(t);
}
@@ -434,7 +397,7 @@ namespace SystemExtensions.Threading
{
//If there are no tasks pending, find a thread with priority above Lowest and downgrade its priority.
Thread t = FindThreadWithAcceptablePriority();
if(t != null)
if (t != null)
{
DowngradeThreadPriority(t);
}
@@ -449,18 +412,10 @@ namespace SystemExtensions.Threading
//Add a thread to the threadpool.
//Reset counter to 0.
statistics.PerformanceCounter = 0;
WorkerThread worker = new WorkerThread();
worker.thread = new Thread(() =>
{
ThreadMainLoop(ref worker);
});
worker.thread.Name = "ThreadPool WorkerThread";
worker.running = true;
worker.thread.Start();
threadpool.Add(worker);
this.CreateAndStartWorkerThread();
}
}
else if(statistics.PerformanceCounter <= -10)
else if (statistics.PerformanceCounter <= -10)
{
if (threadpool.Count > maxThreads / 4)
{
@@ -469,13 +424,13 @@ namespace SystemExtensions.Threading
//Else, abort the thread.
//Reset counter to 0.
WorkerThread worker = threadpool[threadpool.Count - 1];
if (worker.working)
if (worker.Working)
{
worker.running = false;
worker.Running = false;
}
else
{
worker.thread.Abort();
worker.CancellationTokenSource.Cancel();
}
threadpool.RemoveAt(threadpool.Count - 1);
statistics.PerformanceCounter = 0;
@@ -489,11 +444,11 @@ namespace SystemExtensions.Threading
/// <returns>Thread with low priority.</returns>
private Thread FindThreadWithLowPriority()
{
foreach(WorkerThread t in threadpool)
foreach (WorkerThread t in threadpool)
{
if(t.thread.Priority == ThreadPriority.Lowest || t.thread.Priority == ThreadPriority.BelowNormal)
if (t.Thread.Priority == ThreadPriority.Lowest || t.Thread.Priority == ThreadPriority.BelowNormal)
{
return t.thread;
return t.Thread;
}
}
return null;
@@ -506,9 +461,9 @@ namespace SystemExtensions.Threading
{
foreach (WorkerThread t in threadpool)
{
if (t.thread.Priority == ThreadPriority.Normal || t.thread.Priority == ThreadPriority.BelowNormal)
if (t.Thread.Priority == ThreadPriority.Normal || t.Thread.Priority == ThreadPriority.BelowNormal)
{
return t.thread;
return t.Thread;
}
}
return null;
@@ -574,25 +529,27 @@ namespace SystemExtensions.Threading
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
if (!this.disposedValue)
{
if (disposing)
{
if (observer != null)
if (this.observer != null)
{
observer.Abort();
this.observerCancellationTokenSource.Cancel();
this.observer.Join();
}
foreach (WorkerThread worker in threadpool)
{
worker.thread.Abort();
worker.CancellationTokenSource.Cancel();
worker.Thread.Join();
}
threadpool.Clear();
tasks.Clear();
this.threadpool.Clear();
this.tasks.Clear();
}
threadpool = null;
tasks = null;
observer = null;
disposedValue = true;
this.threadpool = null;
this.tasks = null;
this.observer = null;
this.disposedValue = true;
}
}
/// <summary>
@@ -1,14 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class AVLTreeTests
@@ -1,16 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SystemExtensions;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class BinaryHeapTests
@@ -112,7 +105,7 @@ namespace SystemExtensions.Collections.Tests
}
binaryHeap.Clear(false);
int[] array = binaryHeap.ToArray();
if (binaryHeap.Count > 0 || binaryHeap.Capacity != 10)
if (binaryHeap.Count > 0 || binaryHeap.Capacity == 10)
{
Assert.Fail();
}
@@ -1,15 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class FibonacciHeapTests
@@ -1,15 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SystemExtensions;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class PriorityQueueTests
@@ -1,14 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class SkipListTests
@@ -128,6 +123,7 @@ namespace SystemExtensions.Collections.Tests
}
[TestMethod()]
[Ignore("Binary serialization is obsolete and should not be used anymore")]
public void Serialize()
{
SkipList<int> skipList2 = new SkipList<int>();
@@ -1,14 +1,9 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace SystemExtensions.Collections.Tests
namespace System.Collections.Tests
{
[TestClass()]
public class TreapTests
@@ -114,6 +109,7 @@ namespace SystemExtensions.Collections.Tests
}
[TestMethod()]
[Ignore("Binary serialization is obsolete and should not be used anymore")]
public void Serialize()
{
Treap<int> treap2 = new Treap<int>();
@@ -0,0 +1,111 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace System.Extensions.Tests
{
[TestClass]
public class OptionalTests
{
[TestMethod]
public void SomeValueShouldEqualOptional()
{
var value = string.Empty;
var optional = value.ToOptional();
Assert.IsTrue(optional.Equals(value));
}
[TestMethod]
public void OptionalFromNullShouldNotEqual()
{
object value = null;
var optional = value.ToOptional();
Assert.IsFalse(optional.Equals(value));
}
[TestMethod]
public void OptionalFromValueShouldBeSome()
{
var optional = Optional.FromValue<object>(new object());
optional.DoAny(
onNone: () => throw new InvalidOperationException());
}
[TestMethod]
public void OptionalFromNullShouldBeNone()
{
var optional = Optional.FromValue<object>(null);
optional.DoAny(
onSome: _ => throw new InvalidOperationException());
}
[TestMethod]
public void DoShouldExecute()
{
var optional = Optional.FromValue(string.Empty);
var nullOptional = Optional.FromValue<string>(null);
optional.Do(
onSome: _ => { },
onNone: () => throw new InvalidOperationException());
nullOptional.Do(
onSome: _ => throw new InvalidOperationException(),
onNone: () => { });
}
[TestMethod]
public void DoAnyShouldExecute()
{
var optional = Optional.FromValue(string.Empty);
var nullOptional = Optional.FromValue<string>(null);
optional.DoAny(
onNone: () => throw new InvalidOperationException());
nullOptional.DoAny(
onSome: _ => throw new InvalidOperationException());
}
[TestMethod]
public void SwitchShouldExecute()
{
var optional = Optional.FromValue(string.Empty);
var nullOptional = Optional.FromValue<string>(null);
var newValue = optional.Switch(
onSome: _ => string.Empty,
onNone: () => throw new InvalidOperationException())
.ExtractValue();
var newNullValue = nullOptional.Switch<string>(
onSome: _ => throw new InvalidOperationException(),
onNone: () => null)
.ExtractValue();
newValue.Should().Be(string.Empty);
newNullValue.Should().Be(null);
}
[TestMethod]
public void SwitchAnyShouldExecute()
{
var optional = Optional.FromValue(string.Empty);
var nullOptional = Optional.FromValue<string>(null);
var newValue = optional.SwitchAny(
onSome: _ => string.Empty)
.ExtractValue();
var newNullValue = nullOptional.SwitchAny<string>(
onNone: () => null)
.ExtractValue();
newValue.Should().Be(string.Empty);
newNullValue.Should().Be(null);
}
}
}
@@ -0,0 +1,117 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace System.Extensions.Tests
{
[TestClass]
public class ResultTests
{
[TestMethod]
public void SuccessResultShouldCreateFromSuccess()
{
var success = string.Empty;
var result = Result<string, object>.Success(success);
result.DoAny(
onFailure: () => throw new InvalidOperationException());
}
[TestMethod]
public void FailureResultShouldCreateFromFailure()
{
var failure = new object();
var result = Result<string, object>.Failure(failure);
result.DoAny(
onSuccess: () => throw new InvalidOperationException());
}
[TestMethod]
public void DoShouldExecute()
{
var success = string.Empty;
var successResult = Result<string, object>.Success(success);
var failure = new object();
var failedResult = Result<string, object>.Failure(failure);
successResult.Do(
onSuccess: _ => { },
onFailure: _ => throw new InvalidOperationException());
failedResult.Do(
onSuccess: _ => throw new InvalidOperationException(),
onFailure: _ => { });
}
[TestMethod]
public void DoAnyShouldExecute()
{
var success = string.Empty;
var successResult = Result<string, object>.Success(success);
var failure = new object();
var failedResult = Result<string, object>.Failure(failure);
successResult.DoAny(
onSuccess: _ => { });
failedResult.DoAny(
onFailure: _ => { });
}
[TestMethod]
public void SwitchShouldExecute()
{
var success = string.Empty;
var successResult = Result<string, object>.Success(success);
var failure = new object();
var failedResult = Result<string, object>.Failure(failure);
var successSwitch = successResult.Switch(
onSuccess: _ => string.Empty,
onFailure: _ => throw new InvalidOperationException());
var failedSwitch = failedResult.Switch(
onSuccess: _ => throw new InvalidOperationException(),
onFailure: _ => string.Empty);
success.Should().Be(failedSwitch);
}
[TestMethod]
public void SwitchAnyShouldExecute()
{
var success = string.Empty;
var successResult = Result<string, object>.Success(success);
var failure = new object();
var failedResult = Result<string, object>.Failure(failure);
var successSwitch = successResult.SwitchAny(
onSuccess: _ => string.Empty);
var failedSwitch = failedResult.SwitchAny(
onFailure: _ => string.Empty);
success.Should().Be(failedSwitch);
}
[TestMethod]
public void ToOptionalShouldConvert()
{
var success = string.Empty;
var successResult = Result<string, object>.Success(success);
var failure = new object();
var failedResult = Result<string, object>.Failure(failure);
var successOptional = successResult.ToOptional();
var failureOptional = failedResult.ToOptional();
successOptional.Should().NotBeNull();
failureOptional.Should().NotBeNull();
}
}
}
@@ -0,0 +1,321 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Http;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using SystemExtensionsTests.Utils;
namespace SystemExtensionsTests.Http
{
[TestClass]
public class HttpClientTests
{
private const string resourceUrl = "resource";
private static readonly Uri TestAddressUrl = new("https://helloworld.xyz");
private readonly MockHttpMessageHandler handler = new();
private IHttpClient<object> httpClient;
[TestInitialize]
public void TestInitialize()
{
this.httpClient = new HttpClient<object>(this.handler, false)
{
BaseAddress = TestAddressUrl
};
}
[TestMethod]
public async Task HttpClientEmitsCorrectMessages()
{
int messagesEmitted = 0;
this.httpClient.EventEmitted += (sender, message) =>
{
messagesEmitted++;
message.Scope.Should().Be(typeof(object));
message.Method.Should().Be("GetAsync");
message.Url.Should().Be(TestAddressUrl.ToString());
};
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK);
await this.httpClient.GetAsync(TestAddressUrl);
messagesEmitted.Should().Be(1);
}
[TestMethod]
public void SetBaseAddress()
{
this.httpClient.BaseAddress = TestAddressUrl;
this.httpClient.BaseAddress.Should().Be(TestAddressUrl);
}
[TestMethod]
public void SetDefaultRequestHeaders()
{
this.httpClient.DefaultRequestHeaders.TryAddWithoutValidation("someheader", "thisvalue");
this.httpClient.DefaultRequestHeaders.GetValues("someheader").Should().BeEquivalentTo("thisvalue");
}
[TestMethod]
public void SetMaxResponseContentBufferSize()
{
this.httpClient.MaxResponseContentBufferSize = 2000;
this.httpClient.MaxResponseContentBufferSize.Should().Be(2000);
}
[TestMethod]
public void SetTimeout()
{
this.httpClient.Timeout = TimeSpan.FromSeconds(1);
this.httpClient.Timeout.Should().Be(TimeSpan.FromSeconds(1));
}
[TestMethod]
public async Task DeleteAsyncStringReturns200()
{
this.SetupResponse(new Uri(TestAddressUrl, resourceUrl), HttpStatusCode.OK);
var response = await this.httpClient.DeleteAsync(resourceUrl);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
public async Task DeleteAsyncUriReturns200()
{
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK);
var response = await this.httpClient.DeleteAsync(TestAddressUrl);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
[Ignore("NetStandard2.0 implementation doesn't cancel operation when token is cancelled")]
public async Task DeleteAsyncCanceledThrowsTaskCanceledException()
{
this.SetupLongResponse(TestAddressUrl, HttpStatusCode.OK);
var cts = new CancellationTokenSource();
var responseTask = this.httpClient.DeleteAsync(TestAddressUrl, cts.Token);
cts.Cancel();
var awaitAction = new Func<Task<HttpResponseMessage>>(async () =>
{
return await responseTask;
});
await awaitAction.Should().ThrowAsync<TaskCanceledException>();
}
[TestMethod]
public async Task GetAsyncStringReturns200()
{
this.SetupResponse(new Uri(TestAddressUrl, resourceUrl), HttpStatusCode.OK);
var response = await this.httpClient.GetAsync(resourceUrl);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
public async Task GetAsyncUriReturns200()
{
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK);
var response = await this.httpClient.GetAsync(TestAddressUrl);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
[Ignore("NetStandard2.0 implementation doesn't cancel operation when token is cancelled")]
public async Task GetAsyncCanceledThrowsTaskCanceledException()
{
this.SetupLongResponse(TestAddressUrl, HttpStatusCode.OK);
var cts = new CancellationTokenSource();
var responseTask = this.httpClient.GetAsync(TestAddressUrl, cts.Token);
cts.Cancel();
var awaitAction = new Func<Task<HttpResponseMessage>>(async () =>
{
return await responseTask;
});
await awaitAction.Should().ThrowAsync<TaskCanceledException>();
}
[TestMethod]
public async Task PostAsyncStringReturns200()
{
this.SetupResponse(new Uri(TestAddressUrl, resourceUrl), HttpStatusCode.OK);
var response = await this.httpClient.PostAsync(resourceUrl, null);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
public async Task PostAsyncUriReturns200()
{
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK);
var response = await this.httpClient.PostAsync(TestAddressUrl, null);
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
[Ignore("NetStandard2.0 implementation doesn't cancel operation when token is cancelled")]
public async Task PostAsyncCanceledThrowsTaskCanceledException()
{
this.SetupLongResponse(TestAddressUrl, HttpStatusCode.OK);
var cts = new CancellationTokenSource();
var responseTask = this.httpClient.PostAsync(TestAddressUrl, null, cts.Token);
cts.Cancel();
var awaitAction = new Func<Task<HttpResponseMessage>>(async () =>
{
return await responseTask;
});
await awaitAction.Should().ThrowAsync<TaskCanceledException>();
}
[TestMethod]
public async Task SendAsyncUriReturns200()
{
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK);
var response = await this.httpClient.SendAsync(new HttpRequestMessage { RequestUri = TestAddressUrl });
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
[TestMethod]
[Ignore("NetStandard2.0 implementation doesn't cancel operation when token is cancelled")]
public async Task SendAsyncCanceledThrowsTaskCanceledException()
{
this.SetupLongResponse(TestAddressUrl, HttpStatusCode.OK);
var cts = new CancellationTokenSource();
var responseTask = this.httpClient.SendAsync(new HttpRequestMessage { RequestUri = TestAddressUrl }, cts.Token);
cts.Cancel();
var awaitAction = new Func<Task<HttpResponseMessage>>(async () =>
{
return await responseTask;
});
await awaitAction.Should().ThrowAsync<TaskCanceledException>();
}
[TestMethod]
public async Task GetStreamAsyncStringReturns200()
{
var ms = new MemoryStream(new byte[] { 13, 10, 11, 12 });
var sc = new StreamContent(ms);
this.SetupResponse(new Uri(TestAddressUrl, resourceUrl), HttpStatusCode.OK, sc);
var response = await this.httpClient.GetStreamAsync(resourceUrl);
var responseBuffer = new byte[4];
await response.ReadAsync(responseBuffer, 0, 4);
responseBuffer[0].Should().Be(13);
responseBuffer[1].Should().Be(10);
responseBuffer[2].Should().Be(11);
responseBuffer[3].Should().Be(12);
}
[TestMethod]
public async Task GetStreamAsyncUriReturns200()
{
var ms = new MemoryStream(new byte[] { 13, 10, 11, 12 });
var sc = new StreamContent(ms);
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK, sc);
var response = await this.httpClient.GetStreamAsync(TestAddressUrl);
var responseBuffer = new byte[4];
await response.ReadAsync(responseBuffer, 0, 4);
responseBuffer[0].Should().Be(13);
responseBuffer[1].Should().Be(10);
responseBuffer[2].Should().Be(11);
responseBuffer[3].Should().Be(12);
}
[TestMethod]
public async Task GetStringAsyncStringReturns200()
{
var sc = new StringContent("hello");
this.SetupResponse(new Uri(TestAddressUrl, resourceUrl), HttpStatusCode.OK, sc);
var response = await this.httpClient.GetStringAsync(resourceUrl);
response.Should().Be("hello");
}
[TestMethod]
public async Task GetStringAsyncUriReturns200()
{
var sc = new StringContent("hello");
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK, sc);
var response = await this.httpClient.GetStringAsync(TestAddressUrl);
response.Should().Be("hello");
}
[TestMethod]
public async Task GetByteArrayAsyncStringReturns200()
{
var sc = new ByteArrayContent(new byte[4] { 13, 10, 11, 12 });
this.SetupResponse(new Uri(TestAddressUrl, resourceUrl), HttpStatusCode.OK, sc);
var response = await this.httpClient.GetByteArrayAsync(resourceUrl);
response[0].Should().Be(13);
response[1].Should().Be(10);
response[2].Should().Be(11);
response[3].Should().Be(12);
}
[TestMethod]
public async Task GetByteArrayAsyncUriReturns200()
{
var sc = new ByteArrayContent(new byte[4] { 13, 10, 11, 12 });
this.SetupResponse(TestAddressUrl, HttpStatusCode.OK, sc);
var response = await this.httpClient.GetByteArrayAsync(TestAddressUrl);
response[0].Should().Be(13);
response[1].Should().Be(10);
response[2].Should().Be(11);
response[3].Should().Be(12);
}
[TestMethod]
[Ignore("NetStandard2.0 implementation doesn't cancel operation when token is cancelled")]
public async Task CancelPendingRequestThrowsTaskCanceledException()
{
this.SetupLongResponse(TestAddressUrl, HttpStatusCode.OK);
var responseTask = this.httpClient.GetAsync(TestAddressUrl);
this.httpClient.CancelPendingRequests();
var awaitAction = new Func<Task<HttpResponseMessage>>(async () =>
{
return await responseTask;
});
await awaitAction.Should().ThrowAsync<TaskCanceledException>();
}
private void SetupResponse(Uri expectedUri, HttpStatusCode statusCode, HttpContent httpContent = null)
{
this.handler.ResponseResolver = (request) =>
{
request.RequestUri.Should().Be(expectedUri);
return new HttpResponseMessage { StatusCode = statusCode, Content = httpContent };
};
}
private void SetupLongResponse(Uri expectedUri, HttpStatusCode statusCode, HttpContent httpContent = null)
{
this.handler.ResponseResolverAsync = async (request) =>
{
request.RequestUri.Should().Be(expectedUri);
for (int i = 0; i < 10; i++)
{
await Task.Delay(100);
}
return new HttpResponseMessage { StatusCode = statusCode, Content = httpContent };
};
}
}
}
@@ -0,0 +1,72 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace System.Structures.BitStructures.Tests
{
[TestClass]
public class Int32BitStructTests
{
[DataTestMethod]
[DataRow(-1)]
[DataRow(int.MaxValue)]
public void TestSetValueInt(int value)
{
Int32BitStruct int32 = value;
Assert.IsTrue(int32 == value);
}
[DataTestMethod]
[DataRow(1)]
public void TestSetValueUint(int value)
{
Int32BitStruct int32 = value;
Assert.IsTrue(int32 == value);
}
public void TestSetMaxValueUint()
{
Int32BitStruct int32 = uint.MaxValue;
Assert.IsTrue(int32 == uint.MaxValue);
}
[DataTestMethod]
[DataRow(0)]
[DataRow(int.MaxValue)]
[DataRow(int.MinValue)]
public void TestGetBit(int value)
{
Int32BitStruct int32 = value;
Assert.IsTrue(value >= 0 ? int32.Bit31 == 0 : int32.Bit31 == 1);
}
[DataTestMethod]
[DataRow(0)]
[DataRow(1)]
public void TestSetBit(int value)
{
Int32BitStruct int32 = 0;
int32.Bit0 = (uint)value;
Assert.IsTrue(int32 == value);
}
[TestMethod]
public void TestUseCaseExample()
{
// Set value = -1, represented as MSB being 1 and the rest 0.
Int32BitStruct int32 = int.MinValue;
// Test that MSB is 1.
Assert.IsTrue(int32.Bit31 == 1);
// Set MSB to 0 and test that everything else is 0.
int32.Bit31 = 0;
Assert.IsTrue(int32 == 0);
// Set the least 31 significant bits (all besides MSB) to 1.
int32 = int.MaxValue;
// Set the MSB to 1 and test that everything is 1.
int32.Bit31 = 1;
Assert.IsTrue(int32 == uint.MaxValue);
}
}
}
@@ -0,0 +1,108 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace System.Structures.BitStructures.Tests
{
[TestClass]
public class Int64BitStructTests
{
[DataTestMethod]
[DataRow(-1L)]
[DataRow(long.MaxValue)]
public void TestSetValueInt(long value)
{
Int64BitStruct int64 = value;
Assert.IsTrue(int64 == value);
}
[DataTestMethod]
[DataRow(1UL)]
public void TestSetValueUint(long value)
{
Int64BitStruct int64 = value;
Assert.IsTrue(int64 == value);
}
[TestMethod]
public void TestSetMaxValueUint()
{
Int64BitStruct int64 = ulong.MaxValue;
Assert.IsTrue(int64 == ulong.MaxValue);
}
[DataTestMethod]
[DataRow(0)]
[DataRow(long.MaxValue)]
[DataRow(long.MinValue)]
public void TestGetBit(long value)
{
Int64BitStruct int64 = value;
Assert.IsTrue(value >= 0L ? int64.Bit63 == 0 : int64.Bit63 == 1);
}
[DataTestMethod]
[DataRow(0)]
[DataRow(1)]
public void TestSetBit(long value)
{
Int64BitStruct int64 = 0L;
int64.Bit0 = (ulong)value;
Assert.IsTrue(int64 == value);
}
[DataTestMethod]
[DataRow(int.MaxValue, int.MinValue)]
public void TestLowHigh(int low, int high)
{
Int64BitStruct int64 = new Int64BitStruct(low, high);
Int32BitStruct lowStruct = low;
Int32BitStruct highStruct = high;
Assert.IsTrue(int64.Low == lowStruct);
Assert.IsTrue(int64.High == highStruct);
unchecked
{
Assert.IsTrue(int64 == ((ulong)low + ((ulong)high << 32)));
}
}
[TestMethod]
public void TestUseCaseExample()
{
// Set value = -1, represented as MSB being 1 and the rest 0.
Int64BitStruct int64 = long.MinValue;
// Test that MSB is 1.
Assert.IsTrue(int64.Bit63 == 1);
// Set MSB to 0 and test that everything else is 0.
int64.Bit63 = 0;
Assert.IsTrue(int64 == 0UL);
// Set the least 31 significant bits (all besides MSB) to 1.
int64 = long.MaxValue;
// Set the MSB to 1 and test that everything is 1.
int64.Bit63 = 1;
Assert.IsTrue(int64 == ulong.MaxValue);
}
[TestMethod]
public void TestUseCaseExample2()
{
// Set all bits to 1. Check low and high values to be equal to having all 32 bits set.
Int64BitStruct int64 = ulong.MaxValue;
Assert.IsTrue(int64.Low == uint.MaxValue && int64.High == uint.MaxValue);
// Set all 63 least significant bits to 1 and MSB to 0.
int64 = long.MaxValue;
Assert.IsTrue(int64.Bit63 == 0);
// Check that high has all bits besides MSB set to 1 and that low has all bits set to 1.
Assert.IsTrue(int64.High == int.MaxValue && int64.Low == uint.MaxValue);
// Set the MSB back to 1 and check that all bits are set to 1.
int64.Bit63 = 1;
Assert.IsTrue(int64 == ulong.MaxValue);
Assert.IsTrue(int64.High == uint.MaxValue && int64.Low == uint.MaxValue);
}
}
}
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.4" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.4" />
<PackageReference Include="coverlet.collector" Version="3.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj" />
</ItemGroup>
</Project>
@@ -1,15 +1,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SystemExtensions.Threading;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using static SystemExtensions.Threading.PriorityThreadPool;
using static System.Threading.PriorityThreadPool;
namespace SystemExtensions.Threading.Tests
namespace System.Threading.Tests
{
[TestClass()]
public class PriorityThreadPoolTests
@@ -22,7 +14,7 @@ namespace SystemExtensions.Threading.Tests
{
threadPool.Dispose();
threadPool = new PriorityThreadPool();
if (threadPool.NumberOfThreads != System.Environment.ProcessorCount)
if (threadPool.NumberOfThreads != Environment.ProcessorCount)
{
Assert.Fail();
}
@@ -0,0 +1,29 @@
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace SystemExtensionsTests.Utils
{
public sealed class MockHttpMessageHandler : HttpMessageHandler
{
public Func<HttpRequestMessage, HttpResponseMessage> ResponseResolver { get; set; }
public Func<HttpRequestMessage, Task<HttpResponseMessage>> ResponseResolverAsync { get; set; }
public MockHttpMessageHandler()
{
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (this.ResponseResolver is object)
{
return Task.FromResult(this.ResponseResolver(request));
}
else
{
return this.ResponseResolverAsync(request);
}
}
}
}
+27 -12
View File
@@ -1,11 +1,18 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.572
# Visual Studio Version 16
VisualStudioVersion = 16.0.31005.135
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensions", "SystemExtensions\SystemExtensions.csproj", "{55850FF3-70E4-4828-BEEE-39837AC0D24C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard", "SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj", "{4CE9E55C-6016-4631-B8D4-4D763DD05F23}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensionsTests", "SystemExtensionsTests\SystemExtensionsTests.csproj", "{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard.Tests", "SystemExtensions.Tests\SystemExtensions.NetStandard.Tests.csproj", "{33F9C404-EEFF-4EA8-B35C-1B3EA33025A6}"
ProjectSection(ProjectDependencies) = postProject
{4CE9E55C-6016-4631-B8D4-4D763DD05F23} = {4CE9E55C-6016-4631-B8D4-4D763DD05F23}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard.DependencyInjection", "SystemExtensions.NetStandard.DependencyInjection\SystemExtensions.NetStandard.DependencyInjection.csproj", "{53510F19-2E51-423A-BE79-5DE66103E7FC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard.DependencyInjection.Tests", "SystemExtensions.DependencyInjection.Tests\SystemExtensions.NetStandard.DependencyInjection.Tests.csproj", "{1AFA1EEF-CEBA-4046-8466-C9B52979B7DA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -13,14 +20,22 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{55850FF3-70E4-4828-BEEE-39837AC0D24C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{55850FF3-70E4-4828-BEEE-39837AC0D24C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{55850FF3-70E4-4828-BEEE-39837AC0D24C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{55850FF3-70E4-4828-BEEE-39837AC0D24C}.Release|Any CPU.Build.0 = Release|Any CPU
{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}.Release|Any CPU.Build.0 = Release|Any CPU
{4CE9E55C-6016-4631-B8D4-4D763DD05F23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4CE9E55C-6016-4631-B8D4-4D763DD05F23}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4CE9E55C-6016-4631-B8D4-4D763DD05F23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4CE9E55C-6016-4631-B8D4-4D763DD05F23}.Release|Any CPU.Build.0 = Release|Any CPU
{33F9C404-EEFF-4EA8-B35C-1B3EA33025A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{33F9C404-EEFF-4EA8-B35C-1B3EA33025A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{33F9C404-EEFF-4EA8-B35C-1B3EA33025A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{33F9C404-EEFF-4EA8-B35C-1B3EA33025A6}.Release|Any CPU.Build.0 = Release|Any CPU
{53510F19-2E51-423A-BE79-5DE66103E7FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53510F19-2E51-423A-BE79-5DE66103E7FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53510F19-2E51-423A-BE79-5DE66103E7FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53510F19-2E51-423A-BE79-5DE66103E7FC}.Release|Any CPU.Build.0 = Release|Any CPU
{1AFA1EEF-CEBA-4046-8466-C9B52979B7DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1AFA1EEF-CEBA-4046-8466-C9B52979B7DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1AFA1EEF-CEBA-4046-8466-C9B52979B7DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1AFA1EEF-CEBA-4046-8466-C9B52979B7DA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
-39
View File
@@ -1,39 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SystemExtensions
{
/// <summary>
/// Custom implementation of an exception.
/// </summary>
public class ItemNotFoundException : Exception
{
/// <summary>
/// Initializes a new instance of ItemNotFoundException.
/// </summary>
public ItemNotFoundException()
{
}
/// <summary>
/// Initializes a new instance of ItemNotFoundException with a specified error.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public ItemNotFoundException(string message) : base(message)
{
}
/// <summary>
/// Initializes a new instance of ItemNotFoundException with a specified error and a reference to the inner exception that is the cause of this exception.
/// </summary>
/// <param name="message">The message that describes the error.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or null in case there is no inner exception.</param>
public ItemNotFoundException(string message, Exception innerException) : base(message, innerException)
{
}
}
}
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SystemExtensions")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SystemExtensions")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("55850ff3-70e4-4828-beee-39837ac0d24c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
-61
View File
@@ -1,61 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{55850FF3-70E4-4828-BEEE-39837AC0D24C}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SystemExtensions</RootNamespace>
<AssemblyName>SystemExtensions</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\SystemExtensions.xml</DocumentationFile>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Collections\AVLTree.cs" />
<Compile Include="Collections\BinaryHeap.cs" />
<Compile Include="Collections\FibonacciHeap.cs" />
<Compile Include="Collections\IQueue.cs" />
<Compile Include="Collections\PriorityQueue.cs" />
<Compile Include="Collections\SkipList.cs" />
<Compile Include="Collections\Treap.cs" />
<Compile Include="ItemNotFoundException.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Threading\PriorityThreadPool.cs" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SystemExtensionsTests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SystemExtensionsTests")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f9b61261-0a08-4b53-baea-44e05dbbbfe5")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -1,113 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F9B61261-0A08-4B53-BAEA-44E05DBBBFE5}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SystemExtensionsTests</RootNamespace>
<AssemblyName>SystemExtensionsTests</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Xml" />
</ItemGroup>
<Choose>
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
</ItemGroup>
</When>
<Otherwise />
</Choose>
<ItemGroup>
<Compile Include="Collections\AVLTreeTests.cs" />
<Compile Include="Collections\BinaryHeapTests.cs" />
<Compile Include="Collections\FibonacciHeapTests.cs" />
<Compile Include="Collections\PriorityQueueTests.cs" />
<Compile Include="Collections\SkipListTests.cs" />
<Compile Include="Collections\TreapTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Threading\PriorityThreadPoolTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SystemExtensions\SystemExtensions.csproj">
<Project>{55850ff3-70e4-4828-beee-39837ac0d24c}</Project>
<Name>SystemExtensions</Name>
</ProjectReference>
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Private>False</Private>
</Reference>
</ItemGroup>
</When>
</Choose>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets'))" />
</Target>
<Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
-5
View File
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MSTest.TestAdapter" version="1.3.2" targetFramework="net461" />
<package id="MSTest.TestFramework" version="1.3.2" targetFramework="net461" />
</packages>