Compare commits

..

1 Commits

Author SHA1 Message Date
amacocian 6f92b84d47 Merge 16a9208e07 into 3038661f6d 2021-06-02 10:57:10 +00:00
57 changed files with 16 additions and 2344 deletions
+8 -23
View File
@@ -4,7 +4,10 @@ on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
@@ -18,8 +21,7 @@ jobs:
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
Test_Project_Path: SystemExtensions.Tests\SystemExtensions.Tests.csproj
Source_Project_Path: SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj
Actions_Allow_Unsecure_Commands: true
@@ -42,29 +44,12 @@ jobs:
env:
RuntimeIdentifier: win-${{ matrix.targetplatform }}
- name: Build SystemExtensions.NetStandard project
- name: Build Slim 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: Build SystemExtensions.NetStandard.Security project
run: dotnet build SystemExtensions.NetStandard.Security -c $env:Configuration
- name: Push SystemExtensions.NetStandard nuget package
- 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 SystemExtensions.NetStandard.DependencyInjection nuget package
uses: brandedoutcast/publish-nuget@v2.5.5
with:
PROJECT_FILE_PATH: SystemExtensions.NetStandard.DependencyInjection\SystemExtensions.NetStandard.DependencyInjection.csproj
NUGET_KEY: ${{secrets.NUGET_API_KEY}}
- name: Push SystemExtensions.NetStandard.Security nuget package
uses: brandedoutcast/publish-nuget@v2.5.5
with:
PROJECT_FILE_PATH: SystemExtensions.NetStandard.Security\SystemExtensions.NetStandard.Security.csproj
NUGET_KEY: ${{secrets.NUGET_API_KEY}}
+2 -10
View File
@@ -19,10 +19,8 @@ jobs:
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
Sec_Test_Project_Path: SystemExtensions.NetStandard.Security.Tests\SystemExtensions.NetStandard.Security.Tests.csproj
Solution_Path: Slim.sln
Test_Project_Path: SystemExtensions.Tests\SystemExtensions.Tests.csproj
Source_Project_Path: SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj
Actions_Allow_Unsecure_Commands: true
@@ -43,12 +41,6 @@ jobs:
- 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: Execute Security Unit Tests
run: dotnet test $env:Sec_Test_Project_Path
- name: Restore Project
run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
env:
@@ -1,26 +0,0 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.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);
}
}
}
@@ -1,6 +0,0 @@
namespace SystemExtensions.DependencyInjection.Tests.Configuration
{
public sealed class DummyOptions
{
}
}
@@ -1,69 +0,0 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.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);
}
}
}
@@ -1,69 +0,0 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.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);
}
}
}
@@ -1,44 +0,0 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.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();
}
}
}
@@ -1,72 +0,0 @@
using FluentAssertions;
using Microsoft.Extensions.Options;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.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);
}
}
}
@@ -1,69 +0,0 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.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);
}
}
}
@@ -1,48 +0,0 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using System.Configuration;
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();
}
}
}
@@ -1,69 +0,0 @@
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>();
}
}
}
@@ -1,43 +0,0 @@
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();
}
}
}
@@ -1,76 +0,0 @@
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();
}
}
}
@@ -1,30 +0,0 @@
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>();
}
}
}
@@ -1,108 +0,0 @@
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 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);
}
}
}
@@ -1,22 +0,0 @@
<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>
@@ -1,14 +0,0 @@
namespace System.Configuration
{
public sealed class DefaultOptionsManager : IOptionsManager
{
public T GetOptions<T>() where T : class
{
return default;
}
public void UpdateOptions<T>(T value) where T : class
{
}
}
}
@@ -1,9 +0,0 @@
using Microsoft.Extensions.Options;
namespace System.Configuration
{
public interface ILiveOptions<T> : IOptions<T>
where T : class
{
}
}
@@ -1,7 +0,0 @@
namespace System.Configuration
{
public interface ILiveUpdateableOptions<T> : ILiveOptions<T>, IUpdateableOptions<T>
where T : class
{
}
}
@@ -1,10 +0,0 @@
namespace System.Configuration
{
public interface IOptionsManager
{
T GetOptions<T>()
where T : class;
void UpdateOptions<T>(T value)
where T : class;
}
}
@@ -1,13 +0,0 @@
using Microsoft.Extensions.Options;
namespace System.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();
}
}
@@ -1,27 +0,0 @@
using Slim.Resolvers;
namespace System.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);
}
}
}
@@ -1,26 +0,0 @@
using Slim.Resolvers;
namespace System.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);
}
}
}
@@ -1,31 +0,0 @@
using System.Extensions;
namespace System.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);
}
}
}
@@ -1,33 +0,0 @@
using Microsoft.Extensions.Options;
using Slim.Resolvers;
namespace System.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);
}
}
}
@@ -1,33 +0,0 @@
using Slim.Resolvers;
using System.Extensions.Configuration;
namespace System.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);
}
}
}
@@ -1,23 +0,0 @@
using System.Configuration;
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);
}
}
}
@@ -1,141 +0,0 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Slim;
using System.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;
}
}
}
@@ -1,47 +0,0 @@
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;
}
}
}
@@ -1,44 +0,0 @@
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);
}
}
}
@@ -1,39 +0,0 @@
using Microsoft.CorrelationVector;
using Microsoft.Extensions.Logging;
using System.Extensions;
namespace System.Logging
{
public sealed class CVLoggerProvider : ICVLoggerProvider
{
private readonly ILogsWriter logsManager;
private readonly 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)
{
return new CVLogger(categoryName, this);
}
public void Dispose()
{
throw new System.NotImplementedException();
}
}
}
@@ -1,12 +0,0 @@
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}");
}
}
}
@@ -1,9 +0,0 @@
using Microsoft.Extensions.Logging;
namespace System.Logging
{
public interface ICVLoggerProvider : ILoggerProvider
{
void LogEntry(Log log);
}
}
@@ -1,7 +0,0 @@
namespace System.Logging
{
public interface ILogsWriter
{
void WriteLog(Log log);
}
}
@@ -1,50 +0,0 @@
using Microsoft.Extensions.Logging;
using Slim.Resolvers;
using System.Linq;
namespace System.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);
}
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)
{
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
return loggerFactory.CreateLogger(string.Empty);
}
}
}
@@ -1,15 +0,0 @@
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; }
}
}
@@ -1,28 +0,0 @@
<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.1.2</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,105 +0,0 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using SystemExtensions.NetStandard.Security.Encryption;
namespace SystemExtensions.NetStandard.Security.Tests
{
[TestClass]
public class AesEncrypterTests
{
private ISymmetricEncrypter symmetricEncrypter;
private string keyString;
private byte[] keyBytes;
private byte[] ivBytes;
private string ivString;
private string toEncryptString;
private byte[] toEncryptBytes;
[TestInitialize]
public void TestInitialize()
{
this.symmetricEncrypter = new AesEncrypter();
this.keyBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2 };
this.keyString = Convert.ToBase64String(this.keyBytes);
this.ivBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };
this.ivString = Convert.ToBase64String(this.ivBytes);
this.toEncryptBytes = Encoding.UTF8.GetBytes("toEncrypt");
this.toEncryptString = Convert.ToBase64String(this.toEncryptBytes);
}
[TestMethod]
public async Task EncryptDecryptStringWithStringKeyStringIv()
{
var encrypted = await this.symmetricEncrypter.Encrypt(this.keyString, this.ivString, this.toEncryptString).ConfigureAwait(false);
var decrypted = await this.symmetricEncrypter.Decrypt(this.keyString, this.ivString, encrypted).ConfigureAwait(false);
this.toEncryptString.Should().Be(decrypted);
}
[TestMethod]
public async Task EncryptDecryptStringWithByteKeyByteIv()
{
var encrypted = await this.symmetricEncrypter.Encrypt(this.keyBytes, this.ivBytes, this.toEncryptString).ConfigureAwait(false);
var decrypted = await this.symmetricEncrypter.Decrypt(this.keyBytes, this.ivBytes, encrypted).ConfigureAwait(false);
this.toEncryptString.Should().Be(decrypted);
}
[TestMethod]
public async Task EncryptDecryptByteWithStringKeyStringIv()
{
var encrypted = await this.symmetricEncrypter.Encrypt(this.keyString, this.ivString, this.toEncryptBytes).ConfigureAwait(false);
var decrypted = await this.symmetricEncrypter.Decrypt(this.keyString, this.ivString, encrypted).ConfigureAwait(false);
this.toEncryptBytes.Should().BeEquivalentTo(decrypted);
}
[TestMethod]
public async Task EncryptDecryptByteWithByteKeyByteIv()
{
var encrypted = await this.symmetricEncrypter.Encrypt(this.keyBytes, this.ivBytes, this.toEncryptBytes).ConfigureAwait(false);
var decrypted = await this.symmetricEncrypter.Decrypt(this.keyBytes, this.ivBytes, encrypted).ConfigureAwait(false);
this.toEncryptBytes.Should().BeEquivalentTo(decrypted);
}
[TestMethod]
public async Task EncryptDecryptStreamWithStringKeyStringIv()
{
var encrypted = await this.symmetricEncrypter.Encrypt(this.keyString, this.ivString, new MemoryStream(this.toEncryptBytes)).ConfigureAwait(false);
encrypted.Position = 0;
var decrypted = await this.symmetricEncrypter.Decrypt(this.keyString, this.ivString, encrypted).ConfigureAwait(false);
this.toEncryptBytes.Should().BeEquivalentTo(((MemoryStream)decrypted).ToArray());
}
[TestMethod]
public async Task EncryptDecryptStreamWithByteKeyByteIv()
{
var encrypted = await this.symmetricEncrypter.Encrypt(this.keyBytes, this.ivBytes, new MemoryStream(this.toEncryptBytes)).ConfigureAwait(false);
encrypted.Position = 0;
var decrypted = await this.symmetricEncrypter.Decrypt(this.keyBytes, this.ivBytes, encrypted).ConfigureAwait(false);
this.toEncryptBytes.Should().BeEquivalentTo(((MemoryStream)decrypted).ToArray());
}
[TestMethod]
public void GetEncryptionStreamReturnsCryptoStream()
{
var encryptionStream = this.symmetricEncrypter.GetEncryptionStream(this.keyBytes, this.ivBytes, new MemoryStream());
encryptionStream.Should().BeAssignableTo<CryptoStream>();
}
[TestMethod]
public void GetDecryptionStreamReturnsCryptoStream()
{
var encryptionStream = this.symmetricEncrypter.GetDecryptionStream(this.keyBytes, this.ivBytes, new MemoryStream());
encryptionStream.Should().BeAssignableTo<CryptoStream>();
}
}
}
@@ -1,55 +0,0 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
using System.Rng;
namespace SystemExtensions.NetStandard.Security.Tests
{
[TestClass]
public class CryptoRngProviderTests
{
private CryptoRngProvider cryptoRngProvider;
[TestInitialize]
public void TestInitialize()
{
this.cryptoRngProvider = new CryptoRngProvider();
}
[TestMethod]
public void GetBytes_ShouldSetValues()
{
var bytes = new byte[100];
this.cryptoRngProvider.GetBytes(bytes);
bytes.All(b => b == 0).Should().BeFalse();
}
[TestMethod]
public void GetNonZeroBytes_ShouldSetNonZeroValues()
{
var bytes = new byte[100];
this.cryptoRngProvider.GetNonZeroBytes(bytes);
bytes.All(b => b != 0).Should().BeTrue();
}
[TestMethod]
public void GetBytes_ShouldReturnBytes()
{
var bytes = this.cryptoRngProvider.GetBytes(10);
bytes.Length.Should().Be(10);
}
[TestMethod]
public void GetNonZeroBytes_ShouldReturnBytes()
{
var bytes = this.cryptoRngProvider.GetNonZeroBytes(10);
bytes.Length.Should().Be(10);
}
}
}
@@ -1,123 +0,0 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Encryption;
namespace SystemExtensions.NetStandard.Security.Tests
{
[TestClass]
public class SecureStringTests
{
[TestMethod]
public void SecureString_NewSecureString_ReturnsValue()
{
var str = new SecureString("hello");
str.Value.Should().Be("hello");
}
[TestMethod]
public void SecureStringEmpty_AreEqual()
{
var str = SecureString.Empty;
str.Should().Be(SecureString.Empty);
}
[TestMethod]
public void SecureStringEmpty_Equals_StringEmpty()
{
var ss = SecureString.Empty;
var s = string.Empty;
ss.Should().Be(s);
}
[TestMethod]
public void SecureString_Equals_OtherSecureString()
{
var ss1 = new SecureString("Hello");
var ss2 = new SecureString("Hello");
ss1.Equals(ss2).Should().BeTrue();
}
[TestMethod]
[DataRow("hello", "hello", true)]
[DataRow("hello", "henlo", false)]
public void SecureString_EqualOperator_OtherSecureString(string str1, string str2, bool isEqual)
{
var ss1 = new SecureString(str1);
var ss2 = new SecureString(str2);
(ss1 == ss2).Should().Be(isEqual);
}
[TestMethod]
[DataRow("hello", "hello", false)]
[DataRow("hello", "henlo", true)]
public void SecureString_DifferentOperator_OtherSecureString(string str1, string str2, bool isDifferent)
{
var ss1 = new SecureString(str1);
var ss2 = new SecureString(str2);
(ss1 != ss2).Should().Be(isDifferent);
}
[TestMethod]
[DataRow("hello", "hello", true)]
[DataRow("hello", "henlo", false)]
public void SecureString_EqualOperator_String(string str1, string str2, bool isEqual)
{
var ss1 = new SecureString(str1);
(ss1 == str2).Should().Be(isEqual);
}
[TestMethod]
[DataRow("hello", "hello", false)]
[DataRow("hello", "henlo", true)]
public void SecureString_DifferentOperator_String(string str1, string str2, bool isDifferent)
{
var ss1 = new SecureString(str1);
(ss1 != str2).Should().Be(isDifferent);
}
[TestMethod]
public void SecureString_PlusOperator_SecureString()
{
var ss1 = new SecureString("Hello ");
var ss2 = new SecureString("World");
(ss1 + ss2).Should().Be("Hello World");
}
[TestMethod]
public void SecureString_PlusOperator_String()
{
var ss1 = new SecureString("Hello ");
var ss2 = "World";
(ss1 + ss2).Should().Be("Hello World");
}
[TestMethod]
public void SecureString_PlusOperator_Char()
{
var ss1 = new SecureString("Hello ");
var c = 'W';
(ss1 + c).Should().Be("Hello W");
}
[TestMethod]
public void SecureString_WithOptionalEntropy_Matches()
{
SecureString.AddOptionalEntropy(new byte[] { 10, 20, 25, 34, 56, 12, 10, 81, 200, 155, 123, 144, 123, 192, 122, 1 });
var ss1 = new SecureString("Hello");
var ss2 = new SecureString("Hello");
ss1.Should().Be(ss2);
}
}
}
@@ -1,48 +0,0 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using SystemExtensions.NetStandard.Security.Hashing;
namespace SystemExtensions.NetStandard.Security.Tests
{
[TestClass]
public sealed class Sha256HashingServiceTests
{
private readonly IHashingService hashingService = new Sha256HashingService();
private string toHashtString;
private byte[] toHashtBytes;
private Stream toHashStream;
[TestInitialize]
public void TestInitialize()
{
this.toHashtBytes = Encoding.UTF8.GetBytes("toEncrypt");
this.toHashtString = Convert.ToBase64String(this.toHashtBytes);
this.toHashStream = new MemoryStream(this.toHashtBytes);
}
[TestMethod]
public async Task HashString()
{
var hash = await this.hashingService.Hash(this.toHashtString).ConfigureAwait(false);
hash.Should().BeOfType<string>();
}
[TestMethod]
public async Task HashBytes()
{
var hash = await this.hashingService.Hash(this.toHashtBytes).ConfigureAwait(false);
hash.Should().BeOfType<byte[]>();
}
[TestMethod]
public async Task HashStream()
{
var hash = await this.hashingService.Hash(this.toHashStream).ConfigureAwait(false);
hash.Should().BeAssignableTo<Stream>();
}
}
}
@@ -1,21 +0,0 @@
<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="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.Security\SystemExtensions.NetStandard.Security.csproj" />
</ItemGroup>
</Project>
@@ -1,215 +0,0 @@
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
using SystemExtensions.NetStandard.Security.Utilities;
namespace SystemExtensions.NetStandard.Security.Encryption
{
public sealed class AesEncrypter : ISymmetricEncrypter
{
public async Task<string> Decrypt(string key, string iv, string value)
{
using var valueStream = BytesToStream(StringToBytes(value));
using var decryptedStream = await DecryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
return StreamToString(decryptedStream);
}
public async Task<string> Decrypt(byte[] key, byte[] iv, string value)
{
using var valueStream = BytesToStream(StringToBytes(value));
using var decryptedStream = await DecryptInternal(key, iv, valueStream).ConfigureAwait(false);
return StreamToString(decryptedStream);
}
public async Task<byte[]> Decrypt(string key, string iv, byte[] value)
{
using var valueStream = BytesToStream(value);
using var decryptedStream = await DecryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
return StreamToBytes(decryptedStream);
}
public async Task<byte[]> Decrypt(byte[] key, byte[] iv, byte[] value)
{
using var valueStream = BytesToStream(value);
using var decryptedStream = await DecryptInternal(key, iv, valueStream).ConfigureAwait(false);
return StreamToBytes(decryptedStream);
}
public async Task<Stream> Decrypt(string key, string iv, Stream value)
{
return await DecryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
}
public async Task<Stream> Decrypt(byte[] key, byte[] iv, Stream value)
{
return await DecryptInternal(key, iv, value).ConfigureAwait(false);
}
public async Task<string> Encrypt(string key, string iv, string value)
{
using var valueStream = BytesToStream(StringToBytes(value));
using var encryptedStream = await EncryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
return StreamToString(encryptedStream);
}
public async Task<string> Encrypt(byte[] key, byte[] iv, string value)
{
using var valueStream = BytesToStream(StringToBytes(value));
using var encryptedStream = await EncryptInternal(key, iv, valueStream).ConfigureAwait(false);
return StreamToString(encryptedStream);
}
public async Task<byte[]> Encrypt(string key, string iv, byte[] value)
{
using var valueStream = BytesToStream(value);
using var encryptedStream = await EncryptInternal(StringToBytes(key), StringToBytes(iv), valueStream).ConfigureAwait(false);
return StreamToBytes(encryptedStream);
}
public async Task<byte[]> Encrypt(byte[] key, byte[] iv, byte[] value)
{
using var valueStream = BytesToStream(value);
using var encryptedStream = await EncryptInternal(key, iv, valueStream).ConfigureAwait(false);
return StreamToBytes(encryptedStream);
}
public async Task<Stream> Encrypt(string key, string iv, Stream value)
{
if (value is null) throw new ArgumentNullException(nameof(value));
return await EncryptInternal(StringToBytes(key), StringToBytes(iv), value).ConfigureAwait(false);
}
public async Task<Stream> Encrypt(byte[] key, byte[] iv, Stream value)
{
if (value is null) throw new ArgumentNullException(nameof(value));
return await EncryptInternal(key, iv, value).ConfigureAwait(false);
}
public Stream GetEncryptionStream(string key, string iv, Stream outStream)
{
return GetEncryptionStreamInternal(StringToBytes(key), StringToBytes(iv), outStream);
}
public Stream GetEncryptionStream(byte[] key, byte[] iv, Stream outStream)
{
return GetEncryptionStreamInternal(key, iv, outStream);
}
public Stream GetDecryptionStream(string key, string iv, Stream inStream)
{
return GetDecryptionStreamInternal(StringToBytes(key), StringToBytes(iv), inStream);
}
public Stream GetDecryptionStream(byte[] key, byte[] iv, Stream inStream)
{
return GetDecryptionStreamInternal(key, iv, inStream);
}
private static byte[] StreamToBytes(Stream value)
{
value.Position = 0;
byte[] buffer = new byte[1024];
using var ms = new MemoryStream();
int read = -1;
do
{
read = value.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, read);
} while (read > 0);
return ms.ToArray();
}
private static string StreamToString(Stream value)
{
return Convert.ToBase64String(StreamToBytes(value));
}
private static byte[] StringToBytes(string value)
{
return Convert.FromBase64String(value);
}
private static Stream BytesToStream(byte[] value)
{
return new MemoryStream(value);
}
private static async Task<Stream> EncryptInternal(byte[] key, byte[] iv, Stream toEncryptStream)
{
if (key.Length < 32)
{
throw new ArgumentException($"{nameof(key)} must be at least 32 bytes");
}
if (iv.Length < 16)
{
throw new ArgumentException($"{nameof(iv)} must be at least 16 bytes");
}
key = key.Take(32).ToArray();
iv = iv.Take(16).ToArray();
var encryptedMemoryStream = new MemoryStream();
using var cryptoStream = GetEncryptionStreamInternal(key, iv, encryptedMemoryStream);
await toEncryptStream.CopyToAsync(cryptoStream).ConfigureAwait(false);
if (!cryptoStream.HasFlushedFinalBlock)
{
cryptoStream.FlushFinalBlock();
}
encryptedMemoryStream.Position = 0;
return encryptedMemoryStream;
}
private static async Task<Stream> DecryptInternal(byte[] key, byte[] iv, Stream toDecryptStream)
{
if (key.Length < 32)
{
throw new ArgumentException($"{nameof(key)} must be at least 32 bytes");
}
if (iv.Length < 16)
{
throw new ArgumentException($"{nameof(iv)} must be at least 16 bytes");
}
key = key.Take(32).ToArray();
iv = iv.Take(16).ToArray();
var decryptedMemoryStream = new MemoryStream();
using var cryptoStream = GetDecryptionStreamInternal(key, iv, toDecryptStream);
await cryptoStream.CopyToAsync(decryptedMemoryStream).ConfigureAwait(false);
if (!cryptoStream.HasFlushedFinalBlock)
{
cryptoStream.FlushFinalBlock();
}
decryptedMemoryStream.Position = 0;
return decryptedMemoryStream;
}
private static CryptoStream GetEncryptionStreamInternal(byte[] key, byte[] iv, Stream encryptedStream)
{
using var aes = Aes.Create();
aes.Padding = PaddingMode.PKCS7;
var crypto = aes.CreateEncryptor(key, iv);
var cryptoStream = new NotClosingCryptoStream(encryptedStream, crypto, CryptoStreamMode.Write);
return cryptoStream;
}
private static CryptoStream GetDecryptionStreamInternal(byte[] key, byte[] iv, Stream encryptedStream)
{
using var aes = Aes.Create();
aes.Padding = PaddingMode.PKCS7;
var crypto = aes.CreateDecryptor(key, iv);
var cryptoStream = new NotClosingCryptoStream(encryptedStream, crypto, CryptoStreamMode.Read);
return cryptoStream;
}
}
}
@@ -1,25 +0,0 @@
using System.IO;
using System.Threading.Tasks;
namespace SystemExtensions.NetStandard.Security.Encryption
{
public interface ISymmetricEncrypter
{
Stream GetEncryptionStream(string key, string iv, Stream outStream);
Stream GetEncryptionStream(byte[] key, byte[] iv, Stream outStream);
Stream GetDecryptionStream(string key, string iv, Stream inStream);
Stream GetDecryptionStream(byte[] key, byte[] iv, Stream inStream);
Task<string> Encrypt(string key, string iv, string value);
Task<string> Encrypt(byte[] key, byte[] iv, string value);
Task<byte[]> Encrypt(string key, string iv, byte[] value);
Task<byte[]> Encrypt(byte[] key, byte[] iv, byte[] value);
Task<Stream> Encrypt(string key, string iv, Stream value);
Task<Stream> Encrypt(byte[] key, byte[] iv, Stream value);
Task<string> Decrypt(string key, string iv, string value);
Task<string> Decrypt(byte[] key, byte[] iv, string value);
Task<byte[]> Decrypt(string key, string iv, byte[] value);
Task<byte[]> Decrypt(byte[] key, byte[] iv, byte[] value);
Task<Stream> Decrypt(string key, string iv, Stream value);
Task<Stream> Decrypt(byte[] key, byte[] iv, Stream value);
}
}
@@ -1,89 +0,0 @@
using System.Security.Cryptography;
using System.Text;
namespace System.Encryption
{
public sealed class SecureString
{
private static byte[] optionalEntropy;
private byte[] encryptedValue;
public string Value {
get => this.encryptedValue is not null ? Encoding.UTF8.GetString(ProtectedData.Unprotect(this.encryptedValue, optionalEntropy, DataProtectionScope.CurrentUser)) : null;
private set => this.encryptedValue = ProtectedData.Protect(Encoding.UTF8.GetBytes(value), optionalEntropy, DataProtectionScope.CurrentUser);
}
public SecureString(string value)
{
this.Value = value;
}
public override bool Equals(object obj)
{
if (obj is string)
{
return this == (obj as string);
}
else if (obj is SecureString)
{
return this == (obj as SecureString);
}
else
{
return base.Equals(obj);
}
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public override string ToString()
{
return this.Value;
}
public static readonly SecureString Empty = new(string.Empty);
public static implicit operator string(SecureString ss) => ss is null ? string.Empty : ss.Value;
public static implicit operator SecureString(string s) => new(s);
public static SecureString operator +(SecureString ss1, SecureString ss2)
{
if (ss1 is null) throw new ArgumentNullException(nameof(ss1));
if (ss2 is null) throw new ArgumentNullException(nameof(ss2));
return new SecureString(ss1.Value + ss2.Value);
}
public static SecureString operator +(SecureString ss1, string s2)
{
if (ss1 is null) throw new ArgumentNullException(nameof(ss1));
return new SecureString(ss1.Value + s2);
}
public static SecureString operator +(SecureString ss1, char c)
{
if (ss1 is null) throw new ArgumentNullException(nameof(ss1));
return new SecureString(ss1.Value + c);
}
public static bool operator ==(SecureString ss1, SecureString ss2)
{
return ss1?.Value == ss2?.Value;
}
public static bool operator !=(SecureString ss1, SecureString ss2)
{
return !(ss1 == ss2);
}
public static bool operator ==(SecureString ss1, string s2)
{
return ss1?.Value == s2;
}
public static bool operator !=(SecureString ss1, string s2)
{
return !(ss1?.Value == s2);
}
public static void AddOptionalEntropy(byte[] entropy)
{
optionalEntropy = entropy;
}
}
}
@@ -1,12 +0,0 @@
using System.IO;
using System.Threading.Tasks;
namespace SystemExtensions.NetStandard.Security.Hashing
{
public interface IHashingService
{
Task<string> Hash(string raw);
Task<byte[]> Hash(byte[] raw);
Task<Stream> Hash(Stream raw);
}
}
@@ -1,60 +0,0 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading.Tasks;
namespace SystemExtensions.NetStandard.Security.Hashing
{
public sealed class Sha256HashingService : IHashingService
{
public async Task<string> Hash(string raw)
{
using var rawStream = BytesToStream(StringToBytes(raw));
using var hashedStream = await HashInternal(rawStream).ConfigureAwait(false);
return StreamToString(hashedStream);
}
public async Task<byte[]> Hash(byte[] raw)
{
using var rawStream = BytesToStream(raw);
using var hashedStream = await HashInternal(rawStream).ConfigureAwait(false);
return StreamToBytes(hashedStream);
}
public async Task<Stream> Hash(Stream raw)
{
return await HashInternal(raw);
}
private static byte[] StreamToBytes(Stream value)
{
value.Position = 0;
byte[] buffer = new byte[1024];
using var ms = new MemoryStream();
int read = -1;
do
{
read = value.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, read);
} while (read > 0);
return ms.ToArray();
}
private static string StreamToString(Stream value)
{
return Convert.ToBase64String(StreamToBytes(value));
}
private static byte[] StringToBytes(string value)
{
return Convert.FromBase64String(value);
}
private static Stream BytesToStream(byte[] value)
{
return new MemoryStream(value);
}
private static async Task<Stream> HashInternal(Stream raw)
{
if (raw is null) throw new ArgumentNullException(nameof(raw));
using var sha256 = SHA256.Create();
return await Task.Run(() => new MemoryStream(sha256.ComputeHash(raw)));
}
}
}
@@ -1,21 +0,0 @@
MIT License
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
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -1,59 +0,0 @@
using System.Security.Cryptography;
namespace System.Rng
{
public sealed class CryptoRngProvider : ICryptoRngProvider, IDisposable
{
private readonly RNGCryptoServiceProvider rngProvider;
private bool disposedValue;
public CryptoRngProvider()
{
this.rngProvider = new RNGCryptoServiceProvider();
}
public CryptoRngProvider(CspParameters cspParams)
{
this.rngProvider = new RNGCryptoServiceProvider(cspParams);
}
public void GetBytes(byte[] data)
{
this.rngProvider.GetBytes(data);
}
public void GetNonZeroBytes(byte[] data)
{
this.rngProvider.GetNonZeroBytes(data);
}
public byte[] GetBytes(int byteCount)
{
var bytes = new byte[byteCount];
this.GetBytes(bytes);
return bytes;
}
public byte[] GetNonZeroBytes(int byteCount)
{
var bytes = new byte[byteCount];
this.GetNonZeroBytes(bytes);
return bytes;
}
private void Dispose(bool disposing)
{
if (!this.disposedValue)
{
if (disposing)
{
this.rngProvider.Dispose();
}
this.disposedValue = true;
}
}
public void Dispose()
{
this.Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
@@ -1,10 +0,0 @@
namespace System.Rng
{
public interface ICryptoRngProvider
{
public void GetBytes(byte[] data);
public byte[] GetBytes(int byteCount);
public void GetNonZeroBytes(byte[] data);
public byte[] GetNonZeroBytes(int byteCount);
}
}
@@ -1,26 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<RootNamespace>System</RootNamespace>
<Version>1.1.1</Version>
<Authors>Alexandru Macocian</Authors>
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<None Include="../LICENSE">
<Pack>True</Pack>
<PackagePath></PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="5.0.0" />
</ItemGroup>
</Project>
@@ -1,21 +0,0 @@
using System.IO;
using System.Security.Cryptography;
namespace SystemExtensions.NetStandard.Security.Utilities
{
internal sealed class NotClosingCryptoStream : CryptoStream
{
public NotClosingCryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
: base(stream, transform, mode)
{
}
protected override void Dispose(bool disposing)
{
if (!this.HasFlushedFinalBlock)
this.FlushFinalBlock();
base.Dispose(false);
}
}
}
@@ -1,25 +1,7 @@
using Newtonsoft.Json;
namespace System.Extensions
namespace System.Extensions
{
public static class ObjectExtensions
{
public static T Deserialize<T>(this string serialized)
where T : class
{
if (serialized.IsNullOrWhiteSpace()) throw new ArgumentException("Provided serialized string cannot be null or whitespace", nameof(serialized));
return JsonConvert.DeserializeObject<T>(serialized);
}
public static string Serialize<T>(this T obj)
where T : class
{
if (obj is null) throw new ArgumentNullException(nameof(obj));
return JsonConvert.SerializeObject(obj);
}
public static T Cast<T>(this object obj)
{
return (T)obj;
@@ -6,7 +6,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<RootNamespace>System</RootNamespace>
<Version>1.3.1</Version>
<Version>1.3.0</Version>
<Authors>Alexandru Macocian</Authors>
<RepositoryUrl>https://github.com/AlexMacocian/SystemExtensions</RepositoryUrl>
</PropertyGroup>
@@ -18,8 +18,4 @@
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>
@@ -16,14 +16,14 @@ namespace SystemExtensionsTests.Http
{
private const string resourceUrl = "resource";
private static readonly Uri TestAddressUrl = new("https://helloworld.xyz");
private readonly MockHttpMessageHandler handler = new();
private readonly Uri TestAddressUrl = new Uri("https://helloworld.xyz");
private readonly MockHttpMessageHandler handler = new MockHttpMessageHandler();
private IHttpClient<object> httpClient;
[TestInitialize]
public void TestInitialize()
{
this.httpClient = new HttpClient<object>(this.handler, false)
this.httpClient = new HttpClient<object>(handler, false)
{
BaseAddress = TestAddressUrl
};
+1 -25
View File
@@ -5,19 +5,11 @@ VisualStudioVersion = 16.0.31005.135
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard", "SystemExtensions.NetStandard\SystemExtensions.NetStandard.csproj", "{4CE9E55C-6016-4631-B8D4-4D763DD05F23}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemExtensions.NetStandard.Tests", "SystemExtensions.Tests\SystemExtensions.NetStandard.Tests.csproj", "{33F9C404-EEFF-4EA8-B35C-1B3EA33025A6}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensions.Tests", "SystemExtensions.Tests\SystemExtensions.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
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensions.NetStandard.Security", "SystemExtensions.NetStandard.Security\SystemExtensions.NetStandard.Security.csproj", "{BFC5BEE7-2569-45EA-9713-CDB32EED57AA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemExtensions.NetStandard.Security.Tests", "SystemExtensions.NetStandard.Security.Tests\SystemExtensions.NetStandard.Security.Tests.csproj", "{341ECE0F-A8DD-49A0-AE3D-B28D72E85130}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -32,22 +24,6 @@ Global
{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
{BFC5BEE7-2569-45EA-9713-CDB32EED57AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BFC5BEE7-2569-45EA-9713-CDB32EED57AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFC5BEE7-2569-45EA-9713-CDB32EED57AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BFC5BEE7-2569-45EA-9713-CDB32EED57AA}.Release|Any CPU.Build.0 = Release|Any CPU
{341ECE0F-A8DD-49A0-AE3D-B28D72E85130}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{341ECE0F-A8DD-49A0-AE3D-B28D72E85130}.Debug|Any CPU.Build.0 = Debug|Any CPU
{341ECE0F-A8DD-49A0-AE3D-B28D72E85130}.Release|Any CPU.ActiveCfg = Release|Any CPU
{341ECE0F-A8DD-49A0-AE3D-B28D72E85130}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE