cleanup, fixes and additions

This commit is contained in:
Frede Hundewadt 2022-12-12 07:15:46 +01:00
parent 0a0aef7d20
commit 10fe0ac1b6
19 changed files with 3020 additions and 3023 deletions

6
.gitignore vendored
View file

@ -1,3 +1,3 @@
/bin/**/** /bin/**/**
/obj/**/** /obj/**/**
/App_Data/**/** /App_Data/**/**

View file

@ -1,49 +1,49 @@
// *********************************************************************** // ***********************************************************************
// Assembly : FCS.Lib.Utility // Assembly : FCS.Lib.Utility
// Author : FH // Author : FH
// Created : 27-08-2016 // Created : 27-08-2016
// //
// Last Modified By : Frede H. // Last Modified By : Frede H.
// Last Modified On : 02-24-2022 // Last Modified On : 02-24-2022
// *********************************************************************** // ***********************************************************************
// <copyright file="ExtensionsEx.cs" company="FCS"> // <copyright file="ExtensionsEx.cs" company="FCS">
// Copyright (C) 2022 FCS Frede's Computer Services. // Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the Affero GNU General Public License as // it under the terms of the Affero GNU General Public License as
// published by the Free Software Foundation, either version 3 of the // published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version. // License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Affero GNU General Public License for more details. // Affero GNU General Public License for more details.
// //
// You should have received a copy of the Affero GNU General Public License // You should have received a copy of the Affero GNU General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// </copyright> // </copyright>
// <summary></summary> // <summary></summary>
// *********************************************************************** // ***********************************************************************
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace FCS.Lib.Utility namespace FCS.Lib.Utility
{ {
/// <summary> /// <summary>
/// Class ExtensionsEx. /// Class ExtensionsEx.
/// </summary> /// </summary>
public static class ExtensionsEx public static class ExtensionsEx
{ {
/// <summary> /// <summary>
/// ForEach loop /// ForEach loop
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="items">The items.</param> /// <param name="items">The items.</param>
/// <param name="action">The action.</param> /// <param name="action">The action.</param>
public static void ForEach<T>(this IEnumerable<T> items, Action<T> action) public static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
{ {
foreach (var item in items) foreach (var item in items)
action(item); action(item);
} }
} }
} }

View file

@ -1,92 +1,92 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <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')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<LangVersion>10.0</LangVersion> <LangVersion>10.0</LangVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{1F1FECFD-E07E-4B5C-A7F9-67FB89EE94A3}</ProjectGuid> <ProjectGuid>{1F1FECFD-E07E-4B5C-A7F9-67FB89EE94A3}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>FCS.Lib.Utility</RootNamespace> <RootNamespace>FCS.Lib.Utility</RootNamespace>
<AssemblyName>FCS.Lib.Utility</AssemblyName> <AssemblyName>FCS.Lib.Utility</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion> <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic> <Deterministic>true</Deterministic>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\FCS.Lib.Utility.xml</DocumentationFile> <DocumentationFile>bin\Debug\FCS.Lib.Utility.xml</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<SignAssembly>false</SignAssembly> <SignAssembly>false</SignAssembly>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile> </AssemblyOriginatorKeyFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ExtensionsEx.cs" /> <Compile Include="ExtensionsEx.cs" />
<Compile Include="Generators.cs" /> <Compile Include="Generators.cs" />
<Compile Include="GuidGenerator.cs" /> <Compile Include="GuidGenerator.cs" />
<Compile Include="GuidVersion.cs" /> <Compile Include="GuidVersion.cs" />
<Compile Include="IRepository.cs" /> <Compile Include="IRepository.cs" />
<Compile Include="IAsyncReadonlyRepo.cs" /> <Compile Include="IAsyncReadonlyRepo.cs" />
<Compile Include="IRepositoryEx.cs" /> <Compile Include="IRepositoryEx.cs" />
<Compile Include="Mogrify.cs" /> <Compile Include="Mogrify.cs" />
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<DependentUpon>AssemblyInfo.tt</DependentUpon> <DependentUpon>AssemblyInfo.tt</DependentUpon>
</Compile> </Compile>
<Compile Include="VatFormatValidator.cs" /> <Compile Include="VatFormatValidator.cs" />
<Compile Include="QueryHelper.cs" /> <Compile Include="QueryHelper.cs" />
<Compile Include="StringOptions.cs" /> <Compile Include="StringOptions.cs" />
<Compile Include="Squid.cs" /> <Compile Include="Squid.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="LICENSE" /> <None Include="LICENSE" />
<None Include="README.md" /> <None Include="README.md" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include=".gitignore" /> <Content Include=".gitignore" />
<Content Include="Properties\AssemblyInfo.tt"> <Content Include="Properties\AssemblyInfo.tt">
<Generator>TextTemplatingFileGenerator</Generator> <Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>AssemblyInfo.cs</LastGenOutput> <LastGenOutput>AssemblyInfo.cs</LastGenOutput>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
<PreBuildEvent>"C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\TextTransform.exe" -out "$(ProjectDir)Properties\AssemblyInfo.cs" "$(ProjectDir)Properties\AssemblyInfo.tt"</PreBuildEvent> <PreBuildEvent>"C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\TextTransform.exe" -out "$(ProjectDir)Properties\AssemblyInfo.cs" "$(ProjectDir)Properties\AssemblyInfo.tt"</PreBuildEvent>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<ProjectView>ProjectFiles</ProjectView> <ProjectView>ProjectFiles</ProjectView>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View file

@ -1,323 +1,323 @@
// *********************************************************************** // ***********************************************************************
// Assembly : FCS.Lib.Utility // Assembly : FCS.Lib.Utility
// Author : FH // Author : FH
// Created : 2020-07-01 // Created : 2020-07-01
// //
// Last Modified By : FH // Last Modified By : FH
// Last Modified On : 02-24-2022 // Last Modified On : 02-24-2022
// *********************************************************************** // ***********************************************************************
// <copyright file="Generators.cs" company="FCS"> // <copyright file="Generators.cs" company="FCS">
// Copyright (C) 2022 FCS Frede's Computer Services. // Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the Affero GNU General Public License as // it under the terms of the Affero GNU General Public License as
// published by the Free Software Foundation, either version 3 of the // published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version. // License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Affero GNU General Public License for more details. // Affero GNU General Public License for more details.
// //
// You should have received a copy of the Affero GNU General Public License // You should have received a copy of the Affero GNU General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// </copyright> // </copyright>
// <summary></summary> // <summary></summary>
// *********************************************************************** // ***********************************************************************
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
namespace FCS.Lib.Utility namespace FCS.Lib.Utility
{ {
/// <summary> /// <summary>
/// Generators /// Generators
/// </summary> /// </summary>
public static class Generators public static class Generators
{ {
/// <summary> /// <summary>
/// Generate 6 character shortUrl /// Generate 6 character shortUrl
/// </summary> /// </summary>
/// <returns><see cref="string"/> of 6 characters</returns> /// <returns><see cref="string"/> of 6 characters</returns>
public static string ShortUrlGenerator() public static string ShortUrlGenerator()
{ {
return ShortUrlGenerator(6); return ShortUrlGenerator(6);
} }
/// <summary> /// <summary>
/// Generate shortUrl with length /// Generate shortUrl with length
/// </summary> /// </summary>
/// <param name="length">The length.</param> /// <param name="length">The length.</param>
/// <returns><see cref="string"/></returns> /// <returns><see cref="string"/></returns>
/// <remarks>derived from https://sourceforge.net/projects/shorturl-dotnet/</remarks> /// <remarks>derived from https://sourceforge.net/projects/shorturl-dotnet/</remarks>
public static string ShortUrlGenerator(int length) public static string ShortUrlGenerator(int length)
{ {
const string charsLower = "abcdefghijkmnopqrstuvwxyz"; const string charsLower = "abcdefghijkmnopqrstuvwxyz";
const string charsUpper = "ABCDFEGHJKLMNPQRSTUVWXYZ-"; const string charsUpper = "ABCDFEGHJKLMNPQRSTUVWXYZ-";
const string charsNumeric = "1234567890"; const string charsNumeric = "1234567890";
// Create a local array containing supported short-url characters // Create a local array containing supported short-url characters
// grouped by types. // grouped by types.
var charGroups = new[] var charGroups = new[]
{ {
charsLower.ToCharArray(), charsLower.ToCharArray(),
charsUpper.ToCharArray(), charsUpper.ToCharArray(),
charsNumeric.ToCharArray() charsNumeric.ToCharArray()
}; };
// Use this array to track the number of unused characters in each // Use this array to track the number of unused characters in each
// character group. // character group.
var charsLeftInGroup = new int[charGroups.Length]; var charsLeftInGroup = new int[charGroups.Length];
// Initially, all characters in each group are not used. // Initially, all characters in each group are not used.
for (var i = 0; i < charsLeftInGroup.Length; i++) for (var i = 0; i < charsLeftInGroup.Length; i++)
charsLeftInGroup[i] = charGroups[i].Length; charsLeftInGroup[i] = charGroups[i].Length;
// Use this array to track (iterate through) unused character groups. // Use this array to track (iterate through) unused character groups.
var leftGroupsOrder = new int[charGroups.Length]; var leftGroupsOrder = new int[charGroups.Length];
// Initially, all character groups are not used. // Initially, all character groups are not used.
for (var i = 0; i < leftGroupsOrder.Length; i++) for (var i = 0; i < leftGroupsOrder.Length; i++)
leftGroupsOrder[i] = i; leftGroupsOrder[i] = i;
// Using our private randomizer // Using our private randomizer
var random = RandomSeed(); var random = RandomSeed();
// This array will hold short-url characters. // This array will hold short-url characters.
// Allocate appropriate memory for the short-url. // Allocate appropriate memory for the short-url.
var shortUrl = new char[random.Next(length, length)]; var shortUrl = new char[random.Next(length, length)];
// Index of the last non-processed group. // Index of the last non-processed group.
var lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1; var lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
// Generate short-url characters one at a time. // Generate short-url characters one at a time.
for (var i = 0; i < shortUrl.Length; i++) for (var i = 0; i < shortUrl.Length; i++)
{ {
// If only one character group remained unprocessed, process it; // If only one character group remained unprocessed, process it;
// otherwise, pick a random character group from the unprocessed // otherwise, pick a random character group from the unprocessed
// group list. To allow a special character to appear in the // group list. To allow a special character to appear in the
// first position, increment the second parameter of the Next // first position, increment the second parameter of the Next
// function call by one, i.e. lastLeftGroupsOrderIdx + 1. // function call by one, i.e. lastLeftGroupsOrderIdx + 1.
int nextLeftGroupsOrderIdx; int nextLeftGroupsOrderIdx;
if (lastLeftGroupsOrderIdx == 0) if (lastLeftGroupsOrderIdx == 0)
nextLeftGroupsOrderIdx = 0; nextLeftGroupsOrderIdx = 0;
else else
nextLeftGroupsOrderIdx = random.Next(0, nextLeftGroupsOrderIdx = random.Next(0,
lastLeftGroupsOrderIdx); lastLeftGroupsOrderIdx);
// Get the actual index of the character group, from which we will // Get the actual index of the character group, from which we will
// pick the next character. // pick the next character.
var nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx]; var nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];
// Get the index of the last unprocessed characters in this group. // Get the index of the last unprocessed characters in this group.
var lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1; var lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;
// If only one unprocessed character is left, pick it; otherwise, // If only one unprocessed character is left, pick it; otherwise,
// get a random character from the unused character list. // get a random character from the unused character list.
var nextCharIdx = lastCharIdx == 0 ? 0 : random.Next(0, lastCharIdx + 1); var nextCharIdx = lastCharIdx == 0 ? 0 : random.Next(0, lastCharIdx + 1);
// Add this character to the short-url. // Add this character to the short-url.
shortUrl[i] = charGroups[nextGroupIdx][nextCharIdx]; shortUrl[i] = charGroups[nextGroupIdx][nextCharIdx];
// If we processed the last character in this group, start over. // If we processed the last character in this group, start over.
if (lastCharIdx == 0) if (lastCharIdx == 0)
{ {
charsLeftInGroup[nextGroupIdx] = charsLeftInGroup[nextGroupIdx] =
charGroups[nextGroupIdx].Length; charGroups[nextGroupIdx].Length;
} }
// There are more unprocessed characters left. // There are more unprocessed characters left.
else else
{ {
// Swap processed character with the last unprocessed character // Swap processed character with the last unprocessed character
// so that we don't pick it until we process all characters in // so that we don't pick it until we process all characters in
// this group. // this group.
if (lastCharIdx != nextCharIdx) if (lastCharIdx != nextCharIdx)
{ {
(charGroups[nextGroupIdx][lastCharIdx], charGroups[nextGroupIdx][nextCharIdx]) = (charGroups[nextGroupIdx][nextCharIdx], charGroups[nextGroupIdx][lastCharIdx]); (charGroups[nextGroupIdx][lastCharIdx], charGroups[nextGroupIdx][nextCharIdx]) = (charGroups[nextGroupIdx][nextCharIdx], charGroups[nextGroupIdx][lastCharIdx]);
} }
// Decrement the number of unprocessed characters in // Decrement the number of unprocessed characters in
// this group. // this group.
charsLeftInGroup[nextGroupIdx]--; charsLeftInGroup[nextGroupIdx]--;
} }
// If we processed the last group, start all over. // If we processed the last group, start all over.
if (lastLeftGroupsOrderIdx == 0) if (lastLeftGroupsOrderIdx == 0)
{ {
lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1; lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
} }
// There are more unprocessed groups left. // There are more unprocessed groups left.
else else
{ {
// Swap processed group with the last unprocessed group // Swap processed group with the last unprocessed group
// so that we don't pick it until we process all groups. // so that we don't pick it until we process all groups.
if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx) if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
{ {
(leftGroupsOrder[lastLeftGroupsOrderIdx], leftGroupsOrder[nextLeftGroupsOrderIdx]) = (leftGroupsOrder[nextLeftGroupsOrderIdx], leftGroupsOrder[lastLeftGroupsOrderIdx]); (leftGroupsOrder[lastLeftGroupsOrderIdx], leftGroupsOrder[nextLeftGroupsOrderIdx]) = (leftGroupsOrder[nextLeftGroupsOrderIdx], leftGroupsOrder[lastLeftGroupsOrderIdx]);
} }
// Decrement the number of unprocessed groups. // Decrement the number of unprocessed groups.
lastLeftGroupsOrderIdx--; lastLeftGroupsOrderIdx--;
} }
} }
// Convert password characters into a string and return the result. // Convert password characters into a string and return the result.
return new string(shortUrl); return new string(shortUrl);
} }
/// <summary> /// <summary>
/// Username generator /// Username generator
/// </summary> /// </summary>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
/// <returns><see cref="string"/></returns> /// <returns><see cref="string"/></returns>
/// <seealso cref="StringOptions"/> /// <seealso cref="StringOptions"/>
public static string GenerateUsername(StringOptions options = null) public static string GenerateUsername(StringOptions options = null)
{ {
options ??= new StringOptions options ??= new StringOptions
{ {
RequiredLength = 10, RequiredLength = 10,
RequireDigit = true, RequireDigit = true,
RequireLowercase = true, RequireLowercase = true,
RequireUppercase = true, RequireUppercase = true,
RequiredUniqueChars = 4, RequiredUniqueChars = 4,
RequireNonLetterOrDigit = false, RequireNonLetterOrDigit = false,
RequireNonAlphanumeric = false RequireNonAlphanumeric = false
}; };
return GenerateRandomString(options); return GenerateRandomString(options);
} }
/// <summary> /// <summary>
/// Password generator /// Password generator
/// </summary> /// </summary>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
/// <returns><see cref="string"/></returns> /// <returns><see cref="string"/></returns>
/// <seealso cref="StringOptions"/> /// <seealso cref="StringOptions"/>
public static string GeneratePassword(StringOptions options = null) public static string GeneratePassword(StringOptions options = null)
{ {
options ??= new StringOptions options ??= new StringOptions
{ {
RequiredLength = 10, RequiredLength = 10,
RequireDigit = true, RequireDigit = true,
RequireLowercase = true, RequireLowercase = true,
RequireUppercase = true, RequireUppercase = true,
RequiredUniqueChars = 4, RequiredUniqueChars = 4,
RequireNonLetterOrDigit = true, RequireNonLetterOrDigit = true,
RequireNonAlphanumeric = true RequireNonAlphanumeric = true
}; };
return GenerateRandomString(options); return GenerateRandomString(options);
} }
/// <summary> /// <summary>
/// Random string generator with length /// Random string generator with length
/// </summary> /// </summary>
/// <param name="length">The length.</param> /// <param name="length">The length.</param>
/// <returns><see cref="string"/></returns> /// <returns><see cref="string"/></returns>
public static string GenerateRandomText(int length) public static string GenerateRandomText(int length)
{ {
const string consonants = "bcdfghjklmnprstvxzBDFGHJKLMNPRSTVXZ"; const string consonants = "bcdfghjklmnprstvxzBDFGHJKLMNPRSTVXZ";
const string vowels = "aeiouyAEIOUY"; const string vowels = "aeiouyAEIOUY";
var rndString = ""; var rndString = "";
var randomNum = RandomSeed(); var randomNum = RandomSeed();
while (rndString.Length < length) while (rndString.Length < length)
{ {
rndString += consonants[randomNum.Next(consonants.Length)]; rndString += consonants[randomNum.Next(consonants.Length)];
if (rndString.Length < length) if (rndString.Length < length)
rndString += vowels[randomNum.Next(vowels.Length)]; rndString += vowels[randomNum.Next(vowels.Length)];
} }
return rndString; return rndString;
} }
/// <summary> /// <summary>
/// Random string generator - string options /// Random string generator - string options
/// </summary> /// </summary>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
/// <returns><see cref="string"/></returns> /// <returns><see cref="string"/></returns>
public static string GenerateRandomString(StringOptions options = null) public static string GenerateRandomString(StringOptions options = null)
{ {
options ??= new StringOptions options ??= new StringOptions
{ {
RequiredLength = 10, RequiredLength = 10,
RequireDigit = true, RequireDigit = true,
RequireLowercase = true, RequireLowercase = true,
RequireUppercase = true, RequireUppercase = true,
RequiredUniqueChars = 4, RequiredUniqueChars = 4,
RequireNonLetterOrDigit = true, RequireNonLetterOrDigit = true,
RequireNonAlphanumeric = true RequireNonAlphanumeric = true
}; };
var randomChars = new[] var randomChars = new[]
{ {
"ABCDEFGHJKLMNOPQRSTUVWXYZ", // uppercase "ABCDEFGHJKLMNOPQRSTUVWXYZ", // uppercase
"abcdefghijkmnopqrstuvwxyz", // lowercase "abcdefghijkmnopqrstuvwxyz", // lowercase
"0123456789", // digits "0123456789", // digits
"!@$?_-" // non-alphanumeric "!@$?_-" // non-alphanumeric
}; };
// Using our private randomizer // Using our private randomizer
var rand = RandomSeed(); var rand = RandomSeed();
var chars = new List<char>(); var chars = new List<char>();
if (options.RequireUppercase) if (options.RequireUppercase)
chars.Insert(rand.Next(0, chars.Count), chars.Insert(rand.Next(0, chars.Count),
randomChars[0][rand.Next(0, randomChars[0].Length)]); randomChars[0][rand.Next(0, randomChars[0].Length)]);
if (options.RequireLowercase) if (options.RequireLowercase)
chars.Insert(rand.Next(0, chars.Count), chars.Insert(rand.Next(0, chars.Count),
randomChars[1][rand.Next(0, randomChars[1].Length)]); randomChars[1][rand.Next(0, randomChars[1].Length)]);
if (options.RequireDigit) if (options.RequireDigit)
chars.Insert(rand.Next(0, chars.Count), chars.Insert(rand.Next(0, chars.Count),
randomChars[2][rand.Next(0, randomChars[2].Length)]); randomChars[2][rand.Next(0, randomChars[2].Length)]);
if (options.RequireNonAlphanumeric) if (options.RequireNonAlphanumeric)
chars.Insert(rand.Next(0, chars.Count), chars.Insert(rand.Next(0, chars.Count),
randomChars[3][rand.Next(0, randomChars[3].Length)]); randomChars[3][rand.Next(0, randomChars[3].Length)]);
var rcs = randomChars[rand.Next(0, randomChars.Length)]; var rcs = randomChars[rand.Next(0, randomChars.Length)];
for (var i = chars.Count; for (var i = chars.Count;
i < options.RequiredLength i < options.RequiredLength
|| chars.Distinct().Count() < options.RequiredUniqueChars; || chars.Distinct().Count() < options.RequiredUniqueChars;
i++) i++)
chars.Insert(rand.Next(0, chars.Count), chars.Insert(rand.Next(0, chars.Count),
rcs[rand.Next(0, rcs.Length)]); rcs[rand.Next(0, rcs.Length)]);
return new string(chars.ToArray()); return new string(chars.ToArray());
} }
/// <summary> /// <summary>
/// Randomize random using RNGCrypto /// Randomize random using RNGCrypto
/// </summary> /// </summary>
/// <returns><see cref="Random"/></returns> /// <returns><see cref="Random"/></returns>
/// <remarks>derived from https://sourceforge.net/projects/shorturl-dotnet/</remarks> /// <remarks>derived from https://sourceforge.net/projects/shorturl-dotnet/</remarks>
/// <seealso cref="RNGCryptoServiceProvider"/> /// <seealso cref="RNGCryptoServiceProvider"/>
public static Random RandomSeed() public static Random RandomSeed()
{ {
// As the default Random is based on the current time // As the default Random is based on the current time
// so it produces the same "random" number within a second // so it produces the same "random" number within a second
// Use a crypto service to create the seed value // Use a crypto service to create the seed value
// 4-byte array to fill with random bytes // 4-byte array to fill with random bytes
var randomBytes = new byte[4]; var randomBytes = new byte[4];
// Generate 4 random bytes. // Generate 4 random bytes.
using (var rng = new RNGCryptoServiceProvider()) using (var rng = new RNGCryptoServiceProvider())
{ {
rng.GetBytes(randomBytes); rng.GetBytes(randomBytes);
} }
// Convert 4 bytes into a 32-bit integer value. // Convert 4 bytes into a 32-bit integer value.
var seed = ((randomBytes[0] & 0x7f) << 24) | var seed = ((randomBytes[0] & 0x7f) << 24) |
(randomBytes[1] << 16) | (randomBytes[1] << 16) |
(randomBytes[2] << 8) | (randomBytes[2] << 8) |
randomBytes[3]; randomBytes[3];
// Return a truly randomized random generator // Return a truly randomized random generator
return new Random(seed); return new Random(seed);
} }
} }
} }

View file

@ -1,251 +1,251 @@
using System; using System;
using System.Text; using System.Text;
namespace FCS.Lib.Utility namespace FCS.Lib.Utility
{ {
/// <summary> /// <summary>
/// Used for generating UUID based on RFC 4122. /// Used for generating UUID based on RFC 4122.
/// </summary> /// </summary>
/// <seealso href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122 - A Universally Unique IDentifier (UUID) URN Namespace</seealso> /// <seealso href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122 - A Universally Unique IDentifier (UUID) URN Namespace</seealso>
public static class GuidGenerator public static class GuidGenerator
{ {
/// <summary> /// <summary>
/// number of bytes in guid /// number of bytes in guid
/// </summary> /// </summary>
public const int ByteArraySize = 16; public const int ByteArraySize = 16;
/// <summary> /// <summary>
/// multiplex variant info - variant byte /// multiplex variant info - variant byte
/// </summary> /// </summary>
public const int VariantByte = 8; public const int VariantByte = 8;
/// <summary> /// <summary>
/// multiplex variant info - variant byte mask /// multiplex variant info - variant byte mask
/// </summary> /// </summary>
public const int VariantByteMask = 0x3f; public const int VariantByteMask = 0x3f;
/// <summary> /// <summary>
/// multiplex variant info - variant byte shift /// multiplex variant info - variant byte shift
/// </summary> /// </summary>
public const int VariantByteShift = 0x80; public const int VariantByteShift = 0x80;
/// <summary> /// <summary>
/// multiplex version info - version byte /// multiplex version info - version byte
/// </summary> /// </summary>
public const int VersionByte = 7; public const int VersionByte = 7;
/// <summary> /// <summary>
/// multiplex version info - version byte mask /// multiplex version info - version byte mask
/// </summary> /// </summary>
public const int VersionByteMask = 0x0f; public const int VersionByteMask = 0x0f;
/// <summary> /// <summary>
/// multiplex version info version byte shift /// multiplex version info version byte shift
/// </summary> /// </summary>
public const int VersionByteShift = 4; public const int VersionByteShift = 4;
// indexes within the uuid array for certain boundaries // indexes within the uuid array for certain boundaries
private const byte TimestampByte = 0; private const byte TimestampByte = 0;
private const byte GuidClockSequenceByte = 8; private const byte GuidClockSequenceByte = 8;
private const byte NodeByte = 10; private const byte NodeByte = 10;
// offset to move from 1/1/0001, which is 0-time for .NET, to gregorian 0-time of 10/15/1582 // offset to move from 1/1/0001, which is 0-time for .NET, to gregorian 0-time of 10/15/1582
private static readonly DateTimeOffset GregorianCalendarStart = new(1582, 10, 15, 0, 0, 0, TimeSpan.Zero); private static readonly DateTimeOffset GregorianCalendarStart = new(1582, 10, 15, 0, 0, 0, TimeSpan.Zero);
/// <summary> /// <summary>
/// Default clock sequence /// Default clock sequence
/// </summary> /// </summary>
public static byte[] DefaultClockSequence { get; set; } public static byte[] DefaultClockSequence { get; set; }
/// <summary> /// <summary>
/// Default node /// Default node
/// </summary> /// </summary>
public static byte[] DefaultNode { get; set; } public static byte[] DefaultNode { get; set; }
static GuidGenerator() static GuidGenerator()
{ {
DefaultClockSequence = new byte[2]; DefaultClockSequence = new byte[2];
DefaultNode = new byte[6]; DefaultNode = new byte[6];
var random = new Random(); var random = new Random();
random.NextBytes(DefaultClockSequence); random.NextBytes(DefaultClockSequence);
random.NextBytes(DefaultNode); random.NextBytes(DefaultNode);
} }
/// <summary> /// <summary>
/// Set default node /// Set default node
/// </summary> /// </summary>
/// <param name="nodeName"></param> /// <param name="nodeName"></param>
public static void SetDefaultNode(string nodeName) public static void SetDefaultNode(string nodeName)
{ {
var x = nodeName.GetHashCode(); var x = nodeName.GetHashCode();
var node = $"{x:X}"; var node = $"{x:X}";
DefaultNode = Encoding.UTF8.GetBytes(node.ToCharArray(), 0, 6); DefaultNode = Encoding.UTF8.GetBytes(node.ToCharArray(), 0, 6);
} }
/// <summary> /// <summary>
/// Get version /// Get version
/// </summary> /// </summary>
/// <param name="guid"></param> /// <param name="guid"></param>
/// <returns><see cref="GuidVersion"/></returns> /// <returns><see cref="GuidVersion"/></returns>
public static GuidVersion GetVersion(this Guid guid) public static GuidVersion GetVersion(this Guid guid)
{ {
var bytes = guid.ToByteArray(); var bytes = guid.ToByteArray();
return (GuidVersion)((bytes[VersionByte] & 0xFF) >> VersionByteShift); return (GuidVersion)((bytes[VersionByte] & 0xFF) >> VersionByteShift);
} }
/// <summary> /// <summary>
/// Get date time offset from guid /// Get date time offset from guid
/// </summary> /// </summary>
/// <param name="guid"></param> /// <param name="guid"></param>
/// <returns><see cref="DateTimeOffset"/></returns> /// <returns><see cref="DateTimeOffset"/></returns>
public static DateTimeOffset GetDateTimeOffset(Guid guid) public static DateTimeOffset GetDateTimeOffset(Guid guid)
{ {
var bytes = guid.ToByteArray(); var bytes = guid.ToByteArray();
// reverse the version // reverse the version
bytes[VersionByte] &= VersionByteMask; bytes[VersionByte] &= VersionByteMask;
bytes[VersionByte] |= (byte)GuidVersion.TimeBased >> VersionByteShift; bytes[VersionByte] |= (byte)GuidVersion.TimeBased >> VersionByteShift;
var timestampBytes = new byte[8]; var timestampBytes = new byte[8];
Array.Copy(bytes, TimestampByte, timestampBytes, 0, 8); Array.Copy(bytes, TimestampByte, timestampBytes, 0, 8);
var timestamp = BitConverter.ToInt64(timestampBytes, 0); var timestamp = BitConverter.ToInt64(timestampBytes, 0);
var ticks = timestamp + GregorianCalendarStart.Ticks; var ticks = timestamp + GregorianCalendarStart.Ticks;
return new DateTimeOffset(ticks, TimeSpan.Zero); return new DateTimeOffset(ticks, TimeSpan.Zero);
} }
/// <summary> /// <summary>
/// get date time from guid /// get date time from guid
/// </summary> /// </summary>
/// <param name="guid"></param> /// <param name="guid"></param>
/// <returns><see cref="DateTime"/></returns> /// <returns><see cref="DateTime"/></returns>
public static DateTime GetDateTime(Guid guid) public static DateTime GetDateTime(Guid guid)
{ {
return GetDateTimeOffset(guid).DateTime; return GetDateTimeOffset(guid).DateTime;
} }
/// <summary> /// <summary>
/// get local date time from guid /// get local date time from guid
/// </summary> /// </summary>
/// <param name="guid"></param> /// <param name="guid"></param>
/// <returns><see cref="DateTime"/></returns> /// <returns><see cref="DateTime"/></returns>
public static DateTime GetLocalDateTime(Guid guid) public static DateTime GetLocalDateTime(Guid guid)
{ {
return GetDateTimeOffset(guid).LocalDateTime; return GetDateTimeOffset(guid).LocalDateTime;
} }
/// <summary> /// <summary>
/// get utc date time from guid /// get utc date time from guid
/// </summary> /// </summary>
/// <param name="guid"></param> /// <param name="guid"></param>
/// <returns><see cref="DateTime"/></returns> /// <returns><see cref="DateTime"/></returns>
public static DateTime GetUtcDateTime(Guid guid) public static DateTime GetUtcDateTime(Guid guid)
{ {
return GetDateTimeOffset(guid).UtcDateTime; return GetDateTimeOffset(guid).UtcDateTime;
} }
/// <summary> /// <summary>
/// Generate time based guid /// Generate time based guid
/// </summary> /// </summary>
/// <returns><see cref="Guid"/></returns> /// <returns><see cref="Guid"/></returns>
public static Guid GenerateTimeBasedGuid() public static Guid GenerateTimeBasedGuid()
{ {
return GenerateTimeBasedGuid(DateTimeOffset.UtcNow, DefaultClockSequence, DefaultNode); return GenerateTimeBasedGuid(DateTimeOffset.UtcNow, DefaultClockSequence, DefaultNode);
} }
/// <summary> /// <summary>
/// Generate time based guid providing a NodeName string /// Generate time based guid providing a NodeName string
/// </summary> /// </summary>
/// <param name="nodeName"></param> /// <param name="nodeName"></param>
/// <returns><see cref="Guid"/></returns> /// <returns><see cref="Guid"/></returns>
public static Guid GenerateTimeBasedGuid(string nodeName) public static Guid GenerateTimeBasedGuid(string nodeName)
{ {
var x = nodeName.GetHashCode(); var x = nodeName.GetHashCode();
var node = $"{x:X}"; var node = $"{x:X}";
var defaultNode = Encoding.UTF8.GetBytes(node.ToCharArray(), 0, 6); var defaultNode = Encoding.UTF8.GetBytes(node.ToCharArray(), 0, 6);
return GenerateTimeBasedGuid(DateTimeOffset.UtcNow, DefaultClockSequence, defaultNode); return GenerateTimeBasedGuid(DateTimeOffset.UtcNow, DefaultClockSequence, defaultNode);
} }
/// <summary> /// <summary>
/// Generate time based guid providing a valid DateTime object /// Generate time based guid providing a valid DateTime object
/// </summary> /// </summary>
/// <param name="dateTime"></param> /// <param name="dateTime"></param>
/// <returns><see cref="Guid"/></returns> /// <returns><see cref="Guid"/></returns>
public static Guid GenerateTimeBasedGuid(DateTime dateTime) public static Guid GenerateTimeBasedGuid(DateTime dateTime)
{ {
return GenerateTimeBasedGuid(dateTime, DefaultClockSequence, DefaultNode); return GenerateTimeBasedGuid(dateTime, DefaultClockSequence, DefaultNode);
} }
/// <summary> /// <summary>
/// Generate time base guid providing a valid DateTimeOffset object /// Generate time base guid providing a valid DateTimeOffset object
/// </summary> /// </summary>
/// <param name="dateTime"></param> /// <param name="dateTime"></param>
/// <returns><see cref="Guid"/></returns> /// <returns><see cref="Guid"/></returns>
public static Guid GenerateTimeBasedGuid(DateTimeOffset dateTime) public static Guid GenerateTimeBasedGuid(DateTimeOffset dateTime)
{ {
return GenerateTimeBasedGuid(dateTime, DefaultClockSequence, DefaultNode); return GenerateTimeBasedGuid(dateTime, DefaultClockSequence, DefaultNode);
} }
/// <summary> /// <summary>
/// Generate time based guid providing a date time, byte array for clock sequence and node /// Generate time based guid providing a date time, byte array for clock sequence and node
/// </summary> /// </summary>
/// <param name="dateTime"></param> /// <param name="dateTime"></param>
/// <param name="clockSequence"></param> /// <param name="clockSequence"></param>
/// <param name="node"></param> /// <param name="node"></param>
/// <returns><see cref="Guid"/></returns> /// <returns><see cref="Guid"/></returns>
public static Guid GenerateTimeBasedGuid(DateTime dateTime, byte[] clockSequence, byte[] node) public static Guid GenerateTimeBasedGuid(DateTime dateTime, byte[] clockSequence, byte[] node)
{ {
return GenerateTimeBasedGuid(new DateTimeOffset(dateTime), clockSequence, node); return GenerateTimeBasedGuid(new DateTimeOffset(dateTime), clockSequence, node);
} }
/// <summary> /// <summary>
/// Generate time based guid providing a valid DateTimeOffset Object and byte arrays for clock sequence and node /// Generate time based guid providing a valid DateTimeOffset Object and byte arrays for clock sequence and node
/// </summary> /// </summary>
/// <param name="dateTime"></param> /// <param name="dateTime"></param>
/// <param name="clockSequence"></param> /// <param name="clockSequence"></param>
/// <param name="node"></param> /// <param name="node"></param>
/// <returns><see cref="Guid"/></returns> /// <returns><see cref="Guid"/></returns>
/// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception>
public static Guid GenerateTimeBasedGuid(DateTimeOffset dateTime, byte[] clockSequence, byte[] node) public static Guid GenerateTimeBasedGuid(DateTimeOffset dateTime, byte[] clockSequence, byte[] node)
{ {
if (clockSequence == null) if (clockSequence == null)
throw new ArgumentNullException(nameof(clockSequence)); throw new ArgumentNullException(nameof(clockSequence));
if (node == null) if (node == null)
throw new ArgumentNullException(nameof(node)); throw new ArgumentNullException(nameof(node));
if (clockSequence.Length != 2) if (clockSequence.Length != 2)
throw new ArgumentOutOfRangeException(nameof(clockSequence), "The clockSequence must be 2 bytes."); throw new ArgumentOutOfRangeException(nameof(clockSequence), "The clockSequence must be 2 bytes.");
if (node.Length != 6) if (node.Length != 6)
throw new ArgumentOutOfRangeException(nameof(node), "The node must be 6 bytes."); throw new ArgumentOutOfRangeException(nameof(node), "The node must be 6 bytes.");
var ticks = (dateTime - GregorianCalendarStart).Ticks; var ticks = (dateTime - GregorianCalendarStart).Ticks;
var guid = new byte[ByteArraySize]; var guid = new byte[ByteArraySize];
var timestamp = BitConverter.GetBytes(ticks); var timestamp = BitConverter.GetBytes(ticks);
// copy node // copy node
Array.Copy(node, 0, guid, NodeByte, Math.Min(6, node.Length)); Array.Copy(node, 0, guid, NodeByte, Math.Min(6, node.Length));
// copy clock sequence // copy clock sequence
Array.Copy(clockSequence, 0, guid, GuidClockSequenceByte, Math.Min(2, clockSequence.Length)); Array.Copy(clockSequence, 0, guid, GuidClockSequenceByte, Math.Min(2, clockSequence.Length));
// copy timestamp // copy timestamp
Array.Copy(timestamp, 0, guid, TimestampByte, Math.Min(8, timestamp.Length)); Array.Copy(timestamp, 0, guid, TimestampByte, Math.Min(8, timestamp.Length));
// set the variant // set the variant
guid[VariantByte] &= VariantByteMask; guid[VariantByte] &= VariantByteMask;
guid[VariantByte] |= VariantByteShift; guid[VariantByte] |= VariantByteShift;
// set the version // set the version
guid[VersionByte] &= VersionByteMask; guid[VersionByte] &= VersionByteMask;
guid[VersionByte] |= (byte)GuidVersion.TimeBased << VersionByteShift; guid[VersionByte] |= (byte)GuidVersion.TimeBased << VersionByteShift;
return new Guid(guid); return new Guid(guid);
} }
} }
} }

View file

@ -1,25 +1,25 @@
namespace FCS.Lib.Utility namespace FCS.Lib.Utility
{ {
/// <summary> /// <summary>
/// Guid Version Enum /// Guid Version Enum
/// </summary> /// </summary>
public enum GuidVersion public enum GuidVersion
{ {
/// <summary> /// <summary>
/// Time /// Time
/// </summary> /// </summary>
TimeBased = 0x01, TimeBased = 0x01,
/// <summary> /// <summary>
/// Reserved /// Reserved
/// </summary> /// </summary>
Reserved = 0x02, Reserved = 0x02,
/// <summary> /// <summary>
/// Name /// Name
/// </summary> /// </summary>
NameBased = 0x03, NameBased = 0x03,
/// <summary> /// <summary>
/// Random /// Random
/// </summary> /// </summary>
Random = 0x04 Random = 0x04
} }
} }

View file

@ -1,96 +1,96 @@
// *********************************************************************** // ***********************************************************************
// Assembly : FCS.Lib.Utility // Assembly : FCS.Lib.Utility
// Author : FH // Author : FH
// Created : 03-10-2015 // Created : 03-10-2015
// //
// Last Modified By : FH // Last Modified By : FH
// Last Modified On : 02-24-2022 // Last Modified On : 02-24-2022
// *********************************************************************** // ***********************************************************************
// <copyright file="IAsyncReadonlyRepo.cs" company="FCS"> // <copyright file="IAsyncReadonlyRepo.cs" company="FCS">
// Copyright (C) 2022 FCS Frede's Computer Services. // Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the Affero GNU General Public License as // it under the terms of the Affero GNU General Public License as
// published by the Free Software Foundation, either version 3 of the // published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version. // License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Affero GNU General Public License for more details. // Affero GNU General Public License for more details.
// //
// You should have received a copy of the Affero GNU General Public License // You should have received a copy of the Affero GNU General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// </copyright> // </copyright>
// <summary></summary> // <summary></summary>
// *********************************************************************** // ***********************************************************************
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace FCS.Lib.Utility namespace FCS.Lib.Utility
{ {
/// <summary> /// <summary>
/// Interface IRepositoryAsync /// Interface IRepositoryAsync
/// </summary> /// </summary>
/// <typeparam name="TEntity">The type of the t entity.</typeparam> /// <typeparam name="TEntity">The type of the t entity.</typeparam>
public interface IAsyncReadonlyRepo<TEntity> where TEntity : class public interface IAsyncReadonlyRepo<TEntity> where TEntity : class
{ {
/// <summary> /// <summary>
/// Alls this instance. /// Alls this instance.
/// </summary> /// </summary>
/// <returns>IQueryable&lt;TEntity&gt;.</returns> /// <returns>IQueryable&lt;TEntity&gt;.</returns>
IQueryable<TEntity> All(); IQueryable<TEntity> All();
/// <summary> /// <summary>
/// Alls the asynchronous. /// Alls the asynchronous.
/// </summary> /// </summary>
/// <param name="predicate">The predicate.</param> /// <param name="predicate">The predicate.</param>
/// <returns>Task&lt;IList&lt;TEntity&gt;&gt;.</returns> /// <returns>Task&lt;IList&lt;TEntity&gt;&gt;.</returns>
Task<IList<TEntity>> AllAsync(Expression<Func<TEntity, bool>> predicate); Task<IList<TEntity>> AllAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Anies the asynchronous. /// Anies the asynchronous.
/// </summary> /// </summary>
/// <param name="predicate">The predicate.</param> /// <param name="predicate">The predicate.</param>
/// <returns>Task&lt;System.Boolean&gt;.</returns> /// <returns>Task&lt;System.Boolean&gt;.</returns>
Task<bool> AnyAsync(Expression<Func<TEntity, bool>> predicate); Task<bool> AnyAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Finds the asynchronous. /// Finds the asynchronous.
/// </summary> /// </summary>
/// <param name="predicate">The predicate.</param> /// <param name="predicate">The predicate.</param>
/// <returns>Task&lt;TEntity&gt;.</returns> /// <returns>Task&lt;TEntity&gt;.</returns>
Task<TEntity> FindAsync(Expression<Func<TEntity, bool>> predicate); Task<TEntity> FindAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Firsts the asynchronous. /// Firsts the asynchronous.
/// </summary> /// </summary>
/// <param name="predicate">The predicate.</param> /// <param name="predicate">The predicate.</param>
/// <returns>Task&lt;TEntity&gt;.</returns> /// <returns>Task&lt;TEntity&gt;.</returns>
Task<TEntity> FirstAsync(Expression<Func<TEntity, bool>> predicate); Task<TEntity> FirstAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Firsts the or default asynchronous. /// Firsts the or default asynchronous.
/// </summary> /// </summary>
/// <param name="predicate">The predicate.</param> /// <param name="predicate">The predicate.</param>
/// <returns>Task&lt;TEntity&gt;.</returns> /// <returns>Task&lt;TEntity&gt;.</returns>
Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate); Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Anies the specified predicate. /// Anies the specified predicate.
/// </summary> /// </summary>
/// <param name="predicate">The predicate.</param> /// <param name="predicate">The predicate.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
bool Any(Expression<Func<TEntity, bool>> predicate); bool Any(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Gets the by identifier. /// Gets the by identifier.
/// </summary> /// </summary>
/// <param name="id">The identifier.</param> /// <param name="id">The identifier.</param>
/// <returns>TEntity.</returns> /// <returns>TEntity.</returns>
TEntity GetById(string id); TEntity GetById(string id);
} }
} }

View file

@ -1,61 +1,61 @@
// *********************************************************************** // ***********************************************************************
// Assembly : FCS.Lib.Utility // Assembly : FCS.Lib.Utility
// Author : FH // Author : FH
// Created : 05-13-2020 // Created : 05-13-2020
// //
// Last Modified By : FH // Last Modified By : FH
// Last Modified On : 02-24-2022 // Last Modified On : 02-24-2022
// *********************************************************************** // ***********************************************************************
// <copyright file="IRepository.cs" company="FCS"> // <copyright file="IRepository.cs" company="FCS">
// Copyright (C) 2022 FCS Frede's Computer Services. // Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the Affero GNU General Public License as // it under the terms of the Affero GNU General Public License as
// published by the Free Software Foundation, either version 3 of the // published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version. // License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Affero GNU General Public License for more details. // Affero GNU General Public License for more details.
// //
// You should have received a copy of the Affero GNU General Public License // You should have received a copy of the Affero GNU General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// </copyright> // </copyright>
// <summary></summary> // <summary></summary>
// *********************************************************************** // ***********************************************************************
namespace FCS.Lib.Utility namespace FCS.Lib.Utility
{ {
/// <summary> /// <summary>
/// Interface IRepository /// Interface IRepository
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <typeparam name="TKey">The type of the TKey.</typeparam> /// <typeparam name="TKey">The type of the TKey.</typeparam>
public interface IRepository<T, in TKey> where T : class public interface IRepository<T, in TKey> where T : class
{ {
/// <summary> /// <summary>
/// Gets the specified identifier. /// Gets the specified identifier.
/// </summary> /// </summary>
/// <param name="id">The identifier.</param> /// <param name="id">The identifier.</param>
/// <returns>T.</returns> /// <returns>T.</returns>
T GetById(TKey id); T GetById(TKey id);
/// <summary> /// <summary>
/// Creates the specified entity. /// Creates the specified entity.
/// </summary> /// </summary>
/// <param name="entity">The entity.</param> /// <param name="entity">The entity.</param>
void Create(T entity); void Create(T entity);
/// <summary> /// <summary>
/// Updates the specified entity. /// Updates the specified entity.
/// </summary> /// </summary>
/// <param name="entity">The entity.</param> /// <param name="entity">The entity.</param>
void Update(T entity); void Update(T entity);
/// <summary> /// <summary>
/// Deletes the specified identifier. /// Deletes the specified identifier.
/// </summary> /// </summary>
/// <param name="id">The identifier.</param> /// <param name="id">The identifier.</param>
void Delete(TKey id); void Delete(TKey id);
} }
} }

View file

@ -1,127 +1,127 @@
// *********************************************************************** // ***********************************************************************
// Assembly : FCS.Lib.Utility // Assembly : FCS.Lib.Utility
// Author : FH // Author : FH
// Created : 03-10-2015 // Created : 03-10-2015
// //
// Last Modified By : FH // Last Modified By : FH
// Last Modified On : 02-24-2022 // Last Modified On : 02-24-2022
// *********************************************************************** // ***********************************************************************
// <copyright file="IRepositoryEx.cs" company="FCS"> // <copyright file="IRepositoryEx.cs" company="FCS">
// Copyright (C) 2022 FCS Frede's Computer Services. // Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the Affero GNU General Public License as // it under the terms of the Affero GNU General Public License as
// published by the Free Software Foundation, either version 3 of the // published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version. // License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Affero GNU General Public License for more details. // Affero GNU General Public License for more details.
// //
// You should have received a copy of the Affero GNU General Public License // You should have received a copy of the Affero GNU General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// </copyright> // </copyright>
// <summary></summary> // <summary></summary>
// *********************************************************************** // ***********************************************************************
using System; using System;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace FCS.Lib.Utility namespace FCS.Lib.Utility
{ {
/// <summary> /// <summary>
/// Interface IRepositoryEx /// Interface IRepositoryEx
/// </summary> /// </summary>
/// <typeparam name="TEntity">The type of the t entity</typeparam> /// <typeparam name="TEntity">The type of the t entity</typeparam>
public interface IRepositoryEx<TEntity> where TEntity : class public interface IRepositoryEx<TEntity> where TEntity : class
{ {
/// <summary> /// <summary>
/// Get all entities synchronous /// Get all entities synchronous
/// </summary> /// </summary>
/// <param name="predicate">Predicate</param> /// <param name="predicate">Predicate</param>
/// <returns>Task&lt;System.Boolean&gt;</returns> /// <returns>Task&lt;System.Boolean&gt;</returns>
Task<bool> AnyAsync(Expression<Func<TEntity, bool>> predicate); Task<bool> AnyAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Find matching entity asynchronous /// Find matching entity asynchronous
/// </summary> /// </summary>
/// <param name="predicate">Predicate</param> /// <param name="predicate">Predicate</param>
/// <returns>Task&lt;TEntity&gt;</returns> /// <returns>Task&lt;TEntity&gt;</returns>
Task<TEntity> FindAsync(Expression<Func<TEntity, bool>> predicate); Task<TEntity> FindAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Find first matching entity asynchronous /// Find first matching entity asynchronous
/// </summary> /// </summary>
/// <param name="predicate">Predicate</param> /// <param name="predicate">Predicate</param>
/// <returns>Task&lt;TEntity&gt;</returns> /// <returns>Task&lt;TEntity&gt;</returns>
Task<TEntity> FirstAsync(Expression<Func<TEntity, bool>> predicate); Task<TEntity> FirstAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Get first entity matching query or default entity asynchronous /// Get first entity matching query or default entity asynchronous
/// </summary> /// </summary>
/// <param name="predicate">Predicate</param> /// <param name="predicate">Predicate</param>
/// <returns>Task&lt;TEntity&gt;</returns> /// <returns>Task&lt;TEntity&gt;</returns>
Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate); Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Add an entity /// Add an entity
/// </summary> /// </summary>
/// <param name="entity">The entity.</param> /// <param name="entity">The entity.</param>
void Add(TEntity entity); void Add(TEntity entity);
/// <summary> /// <summary>
/// Attach the entity /// Attach the entity
/// </summary> /// </summary>
/// <param name="entity">The entity.</param> /// <param name="entity">The entity.</param>
void Attach(TEntity entity); void Attach(TEntity entity);
/// <summary> /// <summary>
/// Delete the entity /// Delete the entity
/// </summary> /// </summary>
/// <param name="entity">The entity.</param> /// <param name="entity">The entity.</param>
void Delete(TEntity entity); void Delete(TEntity entity);
/// <summary> /// <summary>
/// Anies the specified predicate. /// Anies the specified predicate.
/// </summary> /// </summary>
/// <param name="predicate">The predicate.</param> /// <param name="predicate">The predicate.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
bool Any(Expression<Func<TEntity, bool>> predicate); bool Any(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Get entity by id /// Get entity by id
/// </summary> /// </summary>
/// <param name="id">The identifier.</param> /// <param name="id">The identifier.</param>
/// <returns>TEntity</returns> /// <returns>TEntity</returns>
TEntity GetById(string id); TEntity GetById(string id);
/// <summary> /// <summary>
/// Find first entity matching query /// Find first entity matching query
/// </summary> /// </summary>
/// <param name="predicate">Predicate</param> /// <param name="predicate">Predicate</param>
/// <returns>TEntity</returns> /// <returns>TEntity</returns>
TEntity First(Expression<Func<TEntity, bool>> predicate); TEntity First(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Find first matching entity or default entity /// Find first matching entity or default entity
/// </summary> /// </summary>
/// <param name="predicate">Predicate</param> /// <param name="predicate">Predicate</param>
/// <returns>TEntity</returns> /// <returns>TEntity</returns>
TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate); TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Find all matching entities matching query /// Find all matching entities matching query
/// </summary> /// </summary>
/// <param name="predicate">Predicate</param> /// <param name="predicate">Predicate</param>
/// <returns>IQueryable&lt;TEntity&gt;</returns> /// <returns>IQueryable&lt;TEntity&gt;</returns>
IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> predicate); IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
/// <summary> /// <summary>
/// Get all entities /// Get all entities
/// </summary> /// </summary>
/// <returns>IQueryable&lt;TEntity&gt;</returns> /// <returns>IQueryable&lt;TEntity&gt;</returns>
IQueryable<TEntity> All(); IQueryable<TEntity> All();
} }
} }

1320
LICENSE

File diff suppressed because it is too large Load diff

View file

@ -1,478 +1,478 @@
// *********************************************************************** // ***********************************************************************
// Assembly : FCS.Lib.Utility // Assembly : FCS.Lib.Utility
// Author : FH // Author : FH
// Created : 27-08-2016 // Created : 27-08-2016
// //
// Last Modified By : Frede H. // Last Modified By : Frede H.
// Last Modified On : 02-24-2022 // Last Modified On : 02-24-2022
// *********************************************************************** // ***********************************************************************
// <copyright file="Mogrify.cs" company="FCS"> // <copyright file="Mogrify.cs" company="FCS">
// Copyright (C) 2022 FCS Frede's Computer Services. // Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the Affero GNU General Public License as // it under the terms of the Affero GNU General Public License as
// published by the Free Software Foundation, either version 3 of the // published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version. // License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Affero GNU General Public License for more details. // Affero GNU General Public License for more details.
// //
// You should have received a copy of the Affero GNU General Public License // You should have received a copy of the Affero GNU General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// </copyright> // </copyright>
// <summary></summary> // <summary></summary>
// *********************************************************************** // ***********************************************************************
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace FCS.Lib.Utility namespace FCS.Lib.Utility
{ {
/// <summary> /// <summary>
/// Mogrify between units /// Mogrify between units
/// </summary> /// </summary>
public static class Mogrify public static class Mogrify
{ {
/// <summary> /// <summary>
/// Get month from timestamp /// Get month from timestamp
/// </summary> /// </summary>
/// <param name="timeStamp"></param> /// <param name="timeStamp"></param>
/// <returns>integer</returns> /// <returns>integer</returns>
public static int MonthFromTimestamp(long timeStamp) public static int MonthFromTimestamp(long timeStamp)
{ {
return TimeStampToDateTime(timeStamp).Month; return TimeStampToDateTime(timeStamp).Month;
} }
/// <summary> /// <summary>
/// validate if timestamp occurs in month /// validate if timestamp occurs in month
/// </summary> /// </summary>
/// <param name="timestamp"></param> /// <param name="timestamp"></param>
/// <param name="month"></param> /// <param name="month"></param>
/// <returns>boolean</returns> /// <returns>boolean</returns>
public static bool TimestampInMonth(long timestamp, int month) public static bool TimestampInMonth(long timestamp, int month)
{ {
return TimeStampToDateTime(timestamp).Month == month; return TimeStampToDateTime(timestamp).Month == month;
} }
/// <summary> /// <summary>
/// return iso8601 string from timestamp /// return iso8601 string from timestamp
/// </summary> /// </summary>
/// <param name="timestamp"></param> /// <param name="timestamp"></param>
/// <returns></returns> /// <returns></returns>
public static string TimestampToIso8601(long timestamp) public static string TimestampToIso8601(long timestamp)
{ {
return DateTimeIso8601(TimeStampToDateTime(timestamp)); return DateTimeIso8601(TimeStampToDateTime(timestamp));
} }
/// <summary> /// <summary>
/// return date as ISO /// return date as ISO
/// </summary> /// </summary>
/// <param name="date"></param> /// <param name="date"></param>
/// <returns></returns> /// <returns></returns>
public static string DateTimeIso8601(DateTime date) public static string DateTimeIso8601(DateTime date)
{ {
return date.ToString("o",CultureInfo.InvariantCulture); return date.ToString("o",CultureInfo.InvariantCulture);
} }
/// <summary> /// <summary>
/// Get timestamp range for given datetime /// Get timestamp range for given datetime
/// </summary> /// </summary>
/// <param name="dateTime"></param> /// <param name="dateTime"></param>
/// <returns>dictionary</returns> /// <returns>dictionary</returns>
public static Dictionary<string,long> DateToTimestampRange(DateTime dateTime) public static Dictionary<string,long> DateToTimestampRange(DateTime dateTime)
{ {
var dt1 = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day,0,0,0); var dt1 = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day,0,0,0);
var dt2 = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59); var dt2 = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59);
return new Dictionary<string, long>{ return new Dictionary<string, long>{
{ "lower", DateTimeToTimeStamp(dt1) }, { "lower", DateTimeToTimeStamp(dt1) },
{ "upper", DateTimeToTimeStamp(dt2) } { "upper", DateTimeToTimeStamp(dt2) }
}; };
} }
/// <summary> /// <summary>
/// ISO date to timestamp /// ISO date to timestamp
/// </summary> /// </summary>
/// <param name="isoDateString"></param> /// <param name="isoDateString"></param>
/// <returns>long</returns> /// <returns>long</returns>
public static long IsoDateToTimestamp(string isoDateString) public static long IsoDateToTimestamp(string isoDateString)
{ {
var result = DateTime.TryParse(isoDateString, out var test); var result = DateTime.TryParse(isoDateString, out var test);
if (!result) if (!result)
return 0; return 0;
return $"{test:yyyy-MM-dd}" == isoDateString ? DateTimeToTimeStamp(test) : 0; return $"{test:yyyy-MM-dd}" == isoDateString ? DateTimeToTimeStamp(test) : 0;
} }
/// <summary> /// <summary>
/// ISO date from timestamp /// ISO date from timestamp
/// </summary> /// </summary>
/// <param name="timestamp"></param> /// <param name="timestamp"></param>
/// <returns>string yyyy-MM-dd</returns> /// <returns>string yyyy-MM-dd</returns>
public static string TimestampToIsoDate(long timestamp) public static string TimestampToIsoDate(long timestamp)
{ {
return $"{TimeStampToDateTime(timestamp):yyyy-MM-dd}"; return $"{TimeStampToDateTime(timestamp):yyyy-MM-dd}";
} }
/// <summary> /// <summary>
/// get timestamp from current date time /// get timestamp from current date time
/// </summary> /// </summary>
/// <returns><see cref="long"/></returns> /// <returns><see cref="long"/></returns>
public static long CurrentDateTimeToTimeStamp() public static long CurrentDateTimeToTimeStamp()
{ {
return Convert.ToUInt32(DateTimeToTimeStamp(DateTime.Now)); return Convert.ToUInt32(DateTimeToTimeStamp(DateTime.Now));
} }
/// <summary> /// <summary>
/// get timestamp from date time /// get timestamp from date time
/// </summary> /// </summary>
/// <param name="dateTime"></param> /// <param name="dateTime"></param>
/// <returns><see cref="long"/></returns> /// <returns><see cref="long"/></returns>
public static long DateTimeToTimeStamp(DateTime dateTime) public static long DateTimeToTimeStamp(DateTime dateTime)
{ {
var bigDate = new DateTime(2038, 1, 19, 0, 0, 0, 0); var bigDate = new DateTime(2038, 1, 19, 0, 0, 0, 0);
var nixDate = new DateTime(1970, 1, 1, 0, 0, 0, 0); var nixDate = new DateTime(1970, 1, 1, 0, 0, 0, 0);
if (dateTime >= bigDate) if (dateTime >= bigDate)
return Convert.ToInt64((bigDate - nixDate).TotalSeconds) + return Convert.ToInt64((bigDate - nixDate).TotalSeconds) +
Convert.ToInt64((dateTime - bigDate).TotalSeconds); Convert.ToInt64((dateTime - bigDate).TotalSeconds);
return Convert.ToInt64((dateTime - nixDate).TotalSeconds); return Convert.ToInt64((dateTime - nixDate).TotalSeconds);
} }
/// <summary> /// <summary>
/// get date time from timestamp /// get date time from timestamp
/// </summary> /// </summary>
/// <param name="timeStamp"></param> /// <param name="timeStamp"></param>
/// <returns><see cref="DateTime"/></returns> /// <returns><see cref="DateTime"/></returns>
public static DateTime TimeStampToDateTime(long timeStamp) public static DateTime TimeStampToDateTime(long timeStamp)
{ {
var nixDate = new DateTime(1970, 1, 1, 0, 0, 0, 0); var nixDate = new DateTime(1970, 1, 1, 0, 0, 0, 0);
return nixDate.AddSeconds(timeStamp); return nixDate.AddSeconds(timeStamp);
} }
/// <summary> /// <summary>
/// get seconds from timespan /// get seconds from timespan
/// </summary> /// </summary>
/// <param name="timespan"></param> /// <param name="timespan"></param>
/// <returns><see cref="long"/></returns> /// <returns><see cref="long"/></returns>
public static long TimeSpanToSeconds(TimeSpan timespan) public static long TimeSpanToSeconds(TimeSpan timespan)
{ {
return Convert.ToUInt32(timespan.Ticks / 10000000L); return Convert.ToUInt32(timespan.Ticks / 10000000L);
} }
/// <summary> /// <summary>
/// get timespan from seconds /// get timespan from seconds
/// </summary> /// </summary>
/// <param name="seconds"></param> /// <param name="seconds"></param>
/// <returns><see cref="TimeSpan"/></returns> /// <returns><see cref="TimeSpan"/></returns>
public static TimeSpan SecondsToTimeSpan(long seconds) public static TimeSpan SecondsToTimeSpan(long seconds)
{ {
return TimeSpan.FromTicks(10000000L * seconds); return TimeSpan.FromTicks(10000000L * seconds);
} }
/// <summary> /// <summary>
/// get minutes from timespan /// get minutes from timespan
/// </summary> /// </summary>
/// <param name="timespan"></param> /// <param name="timespan"></param>
/// <returns><see cref="long"/></returns> /// <returns><see cref="long"/></returns>
public static long TimespanToMinutes(TimeSpan timespan) public static long TimespanToMinutes(TimeSpan timespan)
{ {
return Convert.ToUInt32(timespan.Ticks / 10000000L) / 60; return Convert.ToUInt32(timespan.Ticks / 10000000L) / 60;
} }
/// <summary> /// <summary>
/// reverse boolean /// reverse boolean
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns>bool</returns> /// <returns>bool</returns>
public static bool BoolReverse(bool value) public static bool BoolReverse(bool value)
{ {
return !value; return !value;
} }
/// <summary> /// <summary>
/// number from bool /// number from bool
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns>integer</returns> /// <returns>integer</returns>
public static int BoolToInt(bool value) public static int BoolToInt(bool value)
{ {
return value ? 1 : 0; return value ? 1 : 0;
} }
/// <summary> /// <summary>
/// string from bool /// string from bool
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns>string true/false</returns> /// <returns>string true/false</returns>
public static string BoolToString(bool value) public static string BoolToString(bool value)
{ {
return value ? "true" : "false"; return value ? "true" : "false";
} }
/// <summary> /// <summary>
/// get bool from integer /// get bool from integer
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
public static bool IntToBool(int value) public static bool IntToBool(int value)
{ {
return value is > 0 or < 0; return value is > 0 or < 0;
} }
/// <summary> /// <summary>
/// get the number value from enum /// get the number value from enum
/// </summary> /// </summary>
/// <param name="enumeration"></param> /// <param name="enumeration"></param>
/// <returns>int</returns> /// <returns>int</returns>
public static int EnumToInt(object enumeration) public static int EnumToInt(object enumeration)
{ {
return Convert.ToInt32(enumeration, CultureInfo.InvariantCulture); return Convert.ToInt32(enumeration, CultureInfo.InvariantCulture);
} }
/// <summary> /// <summary>
/// get string from enum /// get string from enum
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns>string - name of the enum</returns> /// <returns>string - name of the enum</returns>
public static string EnumToString(Enum value) public static string EnumToString(Enum value)
{ {
return value == null ? string.Empty : value.ToString(); return value == null ? string.Empty : value.ToString();
} }
/// <summary> /// <summary>
/// get list of enum of type T /// get list of enum of type T
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <returns>list of enum</returns> /// <returns>list of enum</returns>
public static IEnumerable<T> GetEnumList<T>() public static IEnumerable<T> GetEnumList<T>()
{ {
return (T[])Enum.GetValues(typeof(T)); return (T[])Enum.GetValues(typeof(T));
} }
/// <summary> /// <summary>
/// get enum from integer of type T /// get enum from integer of type T
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <returns></returns> /// <returns></returns>
public static T IntToEnum<T>(int value) public static T IntToEnum<T>(int value)
{ {
return (T) Enum.ToObject(typeof(T), value); return (T) Enum.ToObject(typeof(T), value);
} }
/// <summary> /// <summary>
/// get string from list using semicolon separator /// get string from list using semicolon separator
/// </summary> /// </summary>
/// <param name="list"></param> /// <param name="list"></param>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <returns></returns> /// <returns></returns>
public static string ListToString<T>(List<T> list) public static string ListToString<T>(List<T> list)
{ {
return ListToString(list, ";"); return ListToString(list, ";");
} }
/// <summary> /// <summary>
/// get string from list using delimiter /// get string from list using delimiter
/// </summary> /// </summary>
/// <param name="list"></param> /// <param name="list"></param>
/// <param name="delimiter"></param> /// <param name="delimiter"></param>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <returns><see cref="string"/></returns> /// <returns><see cref="string"/></returns>
public static string ListToString<T>(List<T> list, string delimiter) public static string ListToString<T>(List<T> list, string delimiter)
{ {
var empty = string.Empty; var empty = string.Empty;
if (list == null) return empty; if (list == null) return empty;
var enumerator = (IEnumerator) list.GetType().GetMethod("GetEnumerator")?.Invoke(list, null); var enumerator = (IEnumerator) list.GetType().GetMethod("GetEnumerator")?.Invoke(list, null);
while (enumerator != null && enumerator.MoveNext()) while (enumerator != null && enumerator.MoveNext())
if (enumerator.Current != null) if (enumerator.Current != null)
empty = string.Concat(empty, enumerator.Current.ToString(), delimiter); empty = string.Concat(empty, enumerator.Current.ToString(), delimiter);
return empty; return empty;
} }
/// <summary> /// <summary>
/// get lowercase dash separated string from Pascal case /// get lowercase dash separated string from Pascal case
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns><see cref="string"/></returns> /// <returns><see cref="string"/></returns>
public static string PascalToLower(string value) public static string PascalToLower(string value)
{ {
var result = string.Join("-", Regex.Split(value, @"(?<!^)(?=[A-Z])").ToArray()); var result = string.Join("-", Regex.Split(value, @"(?<!^)(?=[A-Z])").ToArray());
return result.ToLower(CultureInfo.InvariantCulture); return result.ToLower(CultureInfo.InvariantCulture);
} }
/// <summary> /// <summary>
/// get bool from string /// get bool from string
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns><see cref="bool"/></returns> /// <returns><see cref="bool"/></returns>
public static bool StringToBool(string value) public static bool StringToBool(string value)
{ {
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
return false; return false;
var flag = false; var flag = false;
var upper = value.ToUpperInvariant(); var upper = value.ToUpperInvariant();
if (string.Compare(upper, "true", StringComparison.OrdinalIgnoreCase) == 0) if (string.Compare(upper, "true", StringComparison.OrdinalIgnoreCase) == 0)
{ {
flag = true; flag = true;
} }
else if (string.CompareOrdinal(upper, "false") == 0) else if (string.CompareOrdinal(upper, "false") == 0)
{ {
} }
else if (string.CompareOrdinal(upper, "1") == 0) else if (string.CompareOrdinal(upper, "1") == 0)
{ {
flag = true; flag = true;
} }
return flag; return flag;
} }
/// <summary> /// <summary>
/// get decimal from string /// get decimal from string
/// </summary> /// </summary>
/// <param name="inString"></param> /// <param name="inString"></param>
/// <returns><see cref="decimal"/></returns> /// <returns><see cref="decimal"/></returns>
public static decimal? StringToDecimal(string inString) public static decimal? StringToDecimal(string inString)
{ {
if (string.IsNullOrEmpty(inString)) return 0; if (string.IsNullOrEmpty(inString)) return 0;
return return
!decimal.TryParse(inString.Replace(",", "").Replace(".", ""), NumberStyles.Number, !decimal.TryParse(inString.Replace(",", "").Replace(".", ""), NumberStyles.Number,
CultureInfo.InvariantCulture, out var num) CultureInfo.InvariantCulture, out var num)
? (decimal?) null ? (decimal?) null
: decimal.Divide(num, new decimal((long) 100)); : decimal.Divide(num, new decimal((long) 100));
} }
/// <summary> /// <summary>
/// get enum of type T from string /// get enum of type T from string
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <returns><see cref="Enum"/></returns> /// <returns><see cref="Enum"/></returns>
public static T StringToEnum<T>(string value) public static T StringToEnum<T>(string value)
{ {
return (T)Enum.Parse(typeof(T), value, true); return (T)Enum.Parse(typeof(T), value, true);
} }
/// <summary> /// <summary>
/// get list from string using semicolon /// get list from string using semicolon
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <returns><see cref="List{T}"/></returns> /// <returns><see cref="List{T}"/></returns>
public static List<T> StringToList<T>(string value) public static List<T> StringToList<T>(string value)
{ {
return StringToList<T>(value, ";"); return StringToList<T>(value, ";");
} }
/// <summary> /// <summary>
/// get list from string using delimiter /// get list from string using delimiter
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <param name="delimiter"></param> /// <param name="delimiter"></param>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <returns><see cref="List{T}"/></returns> /// <returns><see cref="List{T}"/></returns>
/// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentNullException"></exception>
public static List<T> StringToList<T>(string value, string delimiter) public static List<T> StringToList<T>(string value, string delimiter)
{ {
if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(value)); if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(value));
if (string.IsNullOrEmpty(delimiter)) throw new ArgumentNullException(nameof(delimiter)); if (string.IsNullOrEmpty(delimiter)) throw new ArgumentNullException(nameof(delimiter));
var ts = new List<T>(); var ts = new List<T>();
var strArrays = value.Split(delimiter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); var strArrays = value.Split(delimiter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
foreach (var str in strArrays) foreach (var str in strArrays)
{ {
var o = typeof(T).FullName; var o = typeof(T).FullName;
if (o == null) continue; if (o == null) continue;
var upperInvariant = o.ToUpperInvariant(); var upperInvariant = o.ToUpperInvariant();
if (string.CompareOrdinal(upperInvariant, "system.string") == 0) if (string.CompareOrdinal(upperInvariant, "system.string") == 0)
{ {
ts.Add((T) Convert.ChangeType(str, typeof(T), CultureInfo.InvariantCulture)); ts.Add((T) Convert.ChangeType(str, typeof(T), CultureInfo.InvariantCulture));
} }
else if (string.CompareOrdinal(upperInvariant, "system.int32") == 0) else if (string.CompareOrdinal(upperInvariant, "system.int32") == 0)
{ {
ts.Add((T) Convert.ChangeType(str, typeof(T), CultureInfo.InvariantCulture)); ts.Add((T) Convert.ChangeType(str, typeof(T), CultureInfo.InvariantCulture));
} }
else if (string.CompareOrdinal(upperInvariant, "system.guid") == 0) else if (string.CompareOrdinal(upperInvariant, "system.guid") == 0)
{ {
var guid = new Guid(str); var guid = new Guid(str);
ts.Add((T) Convert.ChangeType(guid, typeof(T), CultureInfo.InvariantCulture)); ts.Add((T) Convert.ChangeType(guid, typeof(T), CultureInfo.InvariantCulture));
} }
} }
return ts; return ts;
} }
/// <summary> /// <summary>
/// get string from stream (default encoding) /// get string from stream (default encoding)
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns><see cref="Stream"/></returns> /// <returns><see cref="Stream"/></returns>
public static Stream StringToStream(string value) public static Stream StringToStream(string value)
{ {
return StringToStream(value, Encoding.Default); return StringToStream(value, Encoding.Default);
} }
/// <summary> /// <summary>
/// get stream from string (using encoding) /// get stream from string (using encoding)
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <param name="encoding"></param> /// <param name="encoding"></param>
/// <returns><see cref="Stream"/></returns> /// <returns><see cref="Stream"/></returns>
public static Stream StringToStream(string value, Encoding encoding) public static Stream StringToStream(string value, Encoding encoding)
{ {
return encoding == null ? null : new MemoryStream(encoding.GetBytes(value ?? "")); return encoding == null ? null : new MemoryStream(encoding.GetBytes(value ?? ""));
} }
///// <summary> ///// <summary>
///// get string from date time ///// get string from date time
///// </summary> ///// </summary>
///// <returns></returns> ///// <returns></returns>
//public static string CurrentDateTimeToAlpha() //public static string CurrentDateTimeToAlpha()
//{ //{
// var dt = DateTime.UtcNow.ToString("yy MM dd HH MM ss"); // var dt = DateTime.UtcNow.ToString("yy MM dd HH MM ss");
// var sb = new StringBuilder(); // var sb = new StringBuilder();
// var dts = dt.Split(' '); // var dts = dt.Split(' ');
// sb.Append((char) int.Parse(dts[0]) + 65); // sb.Append((char) int.Parse(dts[0]) + 65);
// sb.Append((char) int.Parse(dts[1]) + 65); // sb.Append((char) int.Parse(dts[1]) + 65);
// sb.Append((char) int.Parse(dts[2]) + 97); // sb.Append((char) int.Parse(dts[2]) + 97);
// sb.Append((char) int.Parse(dts[3]) + 65); // sb.Append((char) int.Parse(dts[3]) + 65);
// sb.Append((char) int.Parse(dts[4]) + 97); // sb.Append((char) int.Parse(dts[4]) + 97);
// sb.Append((char) int.Parse(dts[5]) + 97); // sb.Append((char) int.Parse(dts[5]) + 97);
// return sb.ToString(); // return sb.ToString();
//} //}
///// <summary> ///// <summary>
///// integer to letter ///// integer to letter
///// </summary> ///// </summary>
///// <param name="value"></param> ///// <param name="value"></param>
///// <returns>string</returns> ///// <returns>string</returns>
//public static string IntToLetter(int value) //public static string IntToLetter(int value)
//{ //{
// var empty = string.Empty; // var empty = string.Empty;
// var num = 97; // var num = 97;
// var str = ""; // var str = "";
// var num1 = 0; // var num1 = 0;
// var num2 = 97; // var num2 = 97;
// for (var i = 0; i <= value; i++) // for (var i = 0; i <= value; i++)
// { // {
// num1++; // num1++;
// empty = string.Concat(str, Convert.ToString(Convert.ToChar(num), CultureInfo.InvariantCulture)); // empty = string.Concat(str, Convert.ToString(Convert.ToChar(num), CultureInfo.InvariantCulture));
// num++; // num++;
// if (num1 != 26) continue; // if (num1 != 26) continue;
// num1 = 0; // num1 = 0;
// str = Convert.ToChar(num2).ToString(CultureInfo.InvariantCulture); // str = Convert.ToChar(num2).ToString(CultureInfo.InvariantCulture);
// num2++; // num2++;
// num = 97; // num = 97;
// } // }
// return empty; // return empty;
//} //}
} }
} }

View file

@ -1,21 +1,21 @@
// This code was generated by a tool. Any changes made manually will be lost // This code was generated by a tool. Any changes made manually will be lost
// the next time this code is regenerated. // the next time this code is regenerated.
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
[assembly: AssemblyTitle("FCS.Lib.Utility")] [assembly: AssemblyTitle("FCS.Lib.Utility")]
[assembly: AssemblyDescription("FCS.Lib.Utility")] [assembly: AssemblyDescription("FCS.Lib.Utility")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("FCS")] [assembly: AssemblyCompany("FCS")]
[assembly: AssemblyProduct("FCS.Lib.Utility")] [assembly: AssemblyProduct("FCS.Lib.Utility")]
[assembly: AssemblyCopyright("AGPL-3.0-or-later Copyright © FCS 2015-2022")] [assembly: AssemblyCopyright("AGPL-3.0-or-later Copyright © FCS 2015-2022")]
[assembly: AssemblyTrademark("© FCS")] [assembly: AssemblyTrademark("© FCS")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
[assembly: Guid("8D850197-78DB-4D16-A91F-E5BB6E8880A7")] [assembly: Guid("8D850197-78DB-4D16-A91F-E5BB6E8880A7")]
[assembly: AssemblyVersion("1.0.1.0")] [assembly: AssemblyVersion("1.0.22346.0710")]
[assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyFileVersion("1.0.22346.0710")]

View file

@ -1,42 +1,39 @@
<#@ template debug="true" hostspecific="false" language="C#" #> <#@ template debug="true" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #> <#@ output extension=".cs" #>
<# <#
int major = 1; int major = 1;
int minor = 0; // Official == even, Preview == odd int minor = 0; // Official == even, Preview == odd
int build = 1; int build = 1;
int revision = 0; int revision = 0;
string version = String.Format("{0}.{1}.{2}.{3}", major, minor, build, revision); // string version = String.Format("{0}.{1}.{2}.{3}", major, minor, build, revision);
if (minor % 2 == 1) // Preview build // Auto-generate the build and revision
{
// Auto-generate the build and revision DateTime buildTime = DateTime.Now;
DateTime buildTime = DateTime.Now; build = (1000 * (buildTime.Year % 100)) + buildTime.DayOfYear;
revision = (100 * buildTime.Hour) + buildTime.Minute;
build = (1000 * (buildTime.Year % 100)) + buildTime.DayOfYear; string version = String.Format("{0}.{1}.{2:00000}.{3:0000}", major, minor, build, revision);
revision = (100 * buildTime.Hour) + buildTime.Minute; #>
version = String.Format("{0}.{1}.{2:00000}.{3:0000}", major, minor, build, revision); // This code was generated by a tool. Any changes made manually will be lost
} // the next time this code is regenerated.
#>
// This code was generated by a tool. Any changes made manually will be lost using System.Reflection;
// the next time this code is regenerated. using System.Runtime.InteropServices;
using System.Reflection; [assembly: AssemblyTitle("FCS.Lib.Utility")]
using System.Runtime.InteropServices; [assembly: AssemblyDescription("FCS.Lib.Utility")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyTitle("FCS.Lib.Utility")] [assembly: AssemblyCompany("FCS")]
[assembly: AssemblyDescription("FCS.Lib.Utility")] [assembly: AssemblyProduct("FCS.Lib.Utility")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyCopyright("AGPL-3.0-or-later Copyright © FCS 2015-2022")]
[assembly: AssemblyCompany("FCS")] [assembly: AssemblyTrademark("© FCS")]
[assembly: AssemblyProduct("FCS.Lib.Utility")] [assembly: AssemblyCulture("")]
[assembly: AssemblyCopyright("AGPL-3.0-or-later Copyright © FCS 2015-2022")]
[assembly: AssemblyTrademark("© FCS")]
[assembly: AssemblyCulture("")] [assembly: ComVisible(false)]
[assembly: Guid("8D850197-78DB-4D16-A91F-E5BB6E8880A7")]
[assembly: ComVisible(false)] [assembly: AssemblyVersion("<#= version #>")]
[assembly: Guid("8D850197-78DB-4D16-A91F-E5BB6E8880A7")]
[assembly: AssemblyVersion("<#= version #>")]
[assembly: AssemblyFileVersion("<#= version #>")] [assembly: AssemblyFileVersion("<#= version #>")]

View file

@ -1,98 +1,98 @@
// *********************************************************************** // ***********************************************************************
// Assembly : FCS.Lib.Utility // Assembly : FCS.Lib.Utility
// Author : FH // Author : FH
// Created : 01-01-2022 // Created : 01-01-2022
// //
// Last Modified By : FH // Last Modified By : FH
// Last Modified On : 02-24-2022 // Last Modified On : 02-24-2022
// *********************************************************************** // ***********************************************************************
// <copyright file="QueryHelper.cs" company="Frede Hundewadt"> // <copyright file="QueryHelper.cs" company="Frede Hundewadt">
// Copyright (C) 2022 FCS Frede's Computer Services. // Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the Affero GNU General Public License as // it under the terms of the Affero GNU General Public License as
// published by the Free Software Foundation, either version 3 of the // published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version. // License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Affero GNU General Public License for more details. // Affero GNU General Public License for more details.
// //
// You should have received a copy of the Affero GNU General Public License // You should have received a copy of the Affero GNU General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// </copyright> // </copyright>
// <summary></summary> // <summary></summary>
// *********************************************************************** // ***********************************************************************
using System; using System;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
namespace FCS.Lib.Utility namespace FCS.Lib.Utility
{ {
/// <summary> /// <summary>
/// Class QueryHelper. /// Class QueryHelper.
/// </summary> /// </summary>
public static class QueryHelper public static class QueryHelper
{ {
// https://stackoverflow.com/a/45761590 // https://stackoverflow.com/a/45761590
/// <summary> /// <summary>
/// OrderBy /// OrderBy
/// </summary> /// </summary>
/// <param name="q"></param> /// <param name="q"></param>
/// <param name="name"></param> /// <param name="name"></param>
/// <param name="desc"></param> /// <param name="desc"></param>
/// <typeparam name="TModel"></typeparam> /// <typeparam name="TModel"></typeparam>
/// <returns></returns> /// <returns></returns>
public static IQueryable<TModel> OrderBy<TModel> (this IQueryable<TModel> q, string name, bool desc) public static IQueryable<TModel> OrderBy<TModel> (this IQueryable<TModel> q, string name, bool desc)
{ {
var entityType = typeof(TModel); var entityType = typeof(TModel);
var p = entityType.GetProperty(name); var p = entityType.GetProperty(name);
var m = typeof(QueryHelper) var m = typeof(QueryHelper)
.GetMethod("OrderByProperty") .GetMethod("OrderByProperty")
?.MakeGenericMethod(entityType, p.PropertyType); ?.MakeGenericMethod(entityType, p.PropertyType);
return(IQueryable<TModel>) m.Invoke(null, new object[] { q, p , desc }); return(IQueryable<TModel>) m.Invoke(null, new object[] { q, p , desc });
} }
/// <summary> /// <summary>
/// ThenBy /// ThenBy
/// </summary> /// </summary>
/// <param name="q"></param> /// <param name="q"></param>
/// <param name="name"></param> /// <param name="name"></param>
/// <param name="desc"></param> /// <param name="desc"></param>
/// <typeparam name="TModel"></typeparam> /// <typeparam name="TModel"></typeparam>
/// <returns></returns> /// <returns></returns>
public static IQueryable<TModel> ThenBy<TModel> (this IQueryable<TModel> q, string name, bool desc) public static IQueryable<TModel> ThenBy<TModel> (this IQueryable<TModel> q, string name, bool desc)
{ {
var entityType = typeof(TModel); var entityType = typeof(TModel);
var p = entityType.GetProperty(name); var p = entityType.GetProperty(name);
var m = typeof(QueryHelper) var m = typeof(QueryHelper)
.GetMethod("OrderByProperty") .GetMethod("OrderByProperty")
?.MakeGenericMethod(entityType, p.PropertyType); ?.MakeGenericMethod(entityType, p.PropertyType);
return(IQueryable<TModel>) m.Invoke(null, new object[] { q, p , desc }); return(IQueryable<TModel>) m.Invoke(null, new object[] { q, p , desc });
} }
/// <summary> /// <summary>
/// OrderByProperty /// OrderByProperty
/// </summary> /// </summary>
/// <param name="q"></param> /// <param name="q"></param>
/// <param name="p"></param> /// <param name="p"></param>
/// <param name="desc"></param> /// <param name="desc"></param>
/// <typeparam name="TModel"></typeparam> /// <typeparam name="TModel"></typeparam>
/// <typeparam name="TRet"></typeparam> /// <typeparam name="TRet"></typeparam>
/// <returns></returns> /// <returns></returns>
public static IQueryable<TModel> OrderByProperty<TModel, TRet>(IQueryable<TModel> q, PropertyInfo p, bool desc) public static IQueryable<TModel> OrderByProperty<TModel, TRet>(IQueryable<TModel> q, PropertyInfo p, bool desc)
{ {
var pe = Expression.Parameter(typeof(TModel)); var pe = Expression.Parameter(typeof(TModel));
Expression se = Expression.Convert(Expression.Property(pe, p), typeof(object)); Expression se = Expression.Convert(Expression.Property(pe, p), typeof(object));
var exp = Expression.Lambda<Func<TModel, TRet>>(se, pe); var exp = Expression.Lambda<Func<TModel, TRet>>(se, pe);
return desc ? q.OrderByDescending(exp) : q.OrderBy(exp); return desc ? q.OrderByDescending(exp) : q.OrderBy(exp);
} }
}} }}

View file

@ -1 +1 @@
# fcs-utils # fcs-utils

788
Squid.cs
View file

@ -1,395 +1,395 @@
// *********************************************************************** // ***********************************************************************
// Assembly : FCS.Lib.Utility // Assembly : FCS.Lib.Utility
// Author : FH // Author : FH
// Created : 2020-07-01 // Created : 2020-07-01
// //
// Last Modified By : FH // Last Modified By : FH
// Last Modified On : 02-24-2022 // Last Modified On : 02-24-2022
// *********************************************************************** // ***********************************************************************
// <copyright file="Squid.cs" company="FCS"> // <copyright file="Squid.cs" company="FCS">
// Copyright (C) 2022 FCS Frede's Computer Services. // Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the Affero GNU General Public License as // it under the terms of the Affero GNU General Public License as
// published by the Free Software Foundation, either version 3 of the // published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version. // License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// Affero GNU General Public License for more details. // Affero GNU General Public License for more details.
// //
// You should have received a copy of the Affero GNU General Public License // You should have received a copy of the Affero GNU General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html] // along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
// </copyright> // </copyright>
// <summary>Derived from https:github.com/csharpvitamins/CSharpVitamins.ShortGuid</summary> // <summary>Derived from https:github.com/csharpvitamins/CSharpVitamins.ShortGuid</summary>
// *********************************************************************** // ***********************************************************************
using System; using System;
using System.Diagnostics; using System.Diagnostics;
namespace FCS.Lib.Utility namespace FCS.Lib.Utility
{ {
/// <summary> /// <summary>
/// A wrapper for handling URL-safe Base64 encoded globally unique identifiers (GUID). /// A wrapper for handling URL-safe Base64 encoded globally unique identifiers (GUID).
/// </summary> /// </summary>
/// <remarks>Special characters are replaced (/, +) or removed (==). /// <remarks>Special characters are replaced (/, +) or removed (==).
/// Derived from https:github.com/csharpvitamins/CSharpVitamins.ShortGuid</remarks> /// Derived from https:github.com/csharpvitamins/CSharpVitamins.ShortGuid</remarks>
[DebuggerDisplay("{" + nameof(Value) + "}")] [DebuggerDisplay("{" + nameof(Value) + "}")]
public readonly struct Squid : IEquatable<Squid> public readonly struct Squid : IEquatable<Squid>
{ {
/// <summary> /// <summary>
/// A read-only object of the Squid struct. /// A read-only object of the Squid struct.
/// Value is guaranteed to be all zeroes. /// Value is guaranteed to be all zeroes.
/// Equivalent to <see cref="Guid.Empty" />. /// Equivalent to <see cref="Guid.Empty" />.
/// </summary> /// </summary>
public static readonly Squid Empty = new(Guid.Empty); public static readonly Squid Empty = new(Guid.Empty);
/// <summary> /// <summary>
/// Creates a new Squid from a Squid encoded string. /// Creates a new Squid from a Squid encoded string.
/// </summary> /// </summary>
/// <param name="value">A valid Squid encodd string.</param> /// <param name="value">A valid Squid encodd string.</param>
public Squid(string value) public Squid(string value)
{ {
Value = value; Value = value;
Guid = DecodeSquid(value); Guid = DecodeSquid(value);
} }
/// <summary> /// <summary>
/// Creates a new Squid with the given <see cref="System.Guid" />. /// Creates a new Squid with the given <see cref="System.Guid" />.
/// </summary> /// </summary>
/// <param name="obj">A valid System.Guid object.</param> /// <param name="obj">A valid System.Guid object.</param>
public Squid(Guid obj) public Squid(Guid obj)
{ {
Value = EncodeGuid(obj); Value = EncodeGuid(obj);
Guid = obj; Guid = obj;
} }
/// <summary> /// <summary>
/// Gets the underlying <see cref="System.Guid" /> for the encoded Squid. /// Gets the underlying <see cref="System.Guid" /> for the encoded Squid.
/// </summary> /// </summary>
/// <value>The unique identifier.</value> /// <value>The unique identifier.</value>
#pragma warning disable CA1720 // Identifier contains type name #pragma warning disable CA1720 // Identifier contains type name
public Guid Guid { get; } public Guid Guid { get; }
#pragma warning restore CA1720 // Identifier contains type name #pragma warning restore CA1720 // Identifier contains type name
/// <summary> /// <summary>
/// The encoded string value of the <see cref="Guid" /> /// The encoded string value of the <see cref="Guid" />
/// as an URL-safe Base64 string. /// as an URL-safe Base64 string.
/// </summary> /// </summary>
/// <value>The value.</value> /// <value>The value.</value>
public string Value { get; } public string Value { get; }
/// <summary> /// <summary>
/// Returns the encoded URL-safe Base64 string. /// Returns the encoded URL-safe Base64 string.
/// </summary> /// </summary>
/// <returns>A <see cref="string" /> that represents this instance.</returns> /// <returns>A <see cref="string" /> that represents this instance.</returns>
public override string ToString() public override string ToString()
{ {
return Value; return Value;
} }
/// <summary> /// <summary>
/// Returns a value indicating whether this object and a specified object represent the same type and value. /// Returns a value indicating whether this object and a specified object represent the same type and value.
/// Compares for equality against other string, Guid and Squid types. /// Compares for equality against other string, Guid and Squid types.
/// </summary> /// </summary>
/// <param name="obj">A Systerm.String, System.Guid or Squid object</param> /// <param name="obj">A Systerm.String, System.Guid or Squid object</param>
/// <returns><c>true</c> if the specified <see cref="object" /> is equal to this instance; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if the specified <see cref="object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return obj is Squid other && Equals(other); return obj is Squid other && Equals(other);
} }
/// <summary> /// <summary>
/// Equality comparison /// Equality comparison
/// </summary> /// </summary>
/// <param name="obj">A valid Squid object</param> /// <param name="obj">A valid Squid object</param>
/// <returns>A boolean indicating equality.</returns> /// <returns>A boolean indicating equality.</returns>
public bool Equals(Squid obj) public bool Equals(Squid obj)
{ {
return Guid.Equals(obj.Guid) && Value == obj.Value; return Guid.Equals(obj.Guid) && Value == obj.Value;
} }
/// <summary> /// <summary>
/// Returns the hash code for the underlying <see cref="System.Guid" />. /// Returns the hash code for the underlying <see cref="System.Guid" />.
/// </summary> /// </summary>
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns> /// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
public override int GetHashCode() public override int GetHashCode()
{ {
unchecked unchecked
{ {
return (Guid.GetHashCode() * 397) ^ (Value != null ? Value.GetHashCode() : 0); return (Guid.GetHashCode() * 397) ^ (Value != null ? Value.GetHashCode() : 0);
} }
} }
/// <summary> /// <summary>
/// Initialises a new object of the Squid using <see cref="Guid.NewGuid()" />. /// Initialises a new object of the Squid using <see cref="Guid.NewGuid()" />.
/// </summary> /// </summary>
/// <returns>New Squid object</returns> /// <returns>New Squid object</returns>
public static Squid NewGuid() public static Squid NewGuid()
{ {
return new(Guid.NewGuid()); return new(Guid.NewGuid());
} }
/// <summary> /// <summary>
/// Encode string as a new Squid encoded string. /// Encode string as a new Squid encoded string.
/// The encoding is similar to Base64 with /// The encoding is similar to Base64 with
/// non-URL safe characters replaced, and padding removed. /// non-URL safe characters replaced, and padding removed.
/// </summary> /// </summary>
/// <param name="value">A valid <see cref="System.Guid" />.Tostring().</param> /// <param name="value">A valid <see cref="System.Guid" />.Tostring().</param>
/// <returns>A 22 character URL-safe Base64 string.</returns> /// <returns>A 22 character URL-safe Base64 string.</returns>
public static string EncodeString(string value) public static string EncodeString(string value)
{ {
var guid = new Guid(value); var guid = new Guid(value);
return EncodeGuid(guid); return EncodeGuid(guid);
} }
/// <summary> /// <summary>
/// Encode a <see cref="System.Guid" /> object to Squid. /// Encode a <see cref="System.Guid" /> object to Squid.
/// The encoding is similar to Base64 with /// The encoding is similar to Base64 with
/// non-URL safe characters replaced, and padding removed. /// non-URL safe characters replaced, and padding removed.
/// </summary> /// </summary>
/// <param name="obj">A valid <see cref="System.Guid" /> object.</param> /// <param name="obj">A valid <see cref="System.Guid" /> object.</param>
/// <returns>A 22 character URL-safe Base64 string.</returns> /// <returns>A 22 character URL-safe Base64 string.</returns>
public static string EncodeGuid(Guid obj) public static string EncodeGuid(Guid obj)
{ {
var encoded = Convert.ToBase64String(obj.ToByteArray()); var encoded = Convert.ToBase64String(obj.ToByteArray());
encoded = encoded encoded = encoded
.Replace("/", "_") .Replace("/", "_")
.Replace("+", "-"); .Replace("+", "-");
return encoded.Substring(0, 22); return encoded.Substring(0, 22);
} }
/// <summary> /// <summary>
/// Decode Squid string to a <see cref="System.Guid" />. /// Decode Squid string to a <see cref="System.Guid" />.
/// See also <seealso cref="TryDecode(string, out System.Guid)" /> or /// See also <seealso cref="TryDecode(string, out System.Guid)" /> or
/// <seealso cref="TryParse(string, out System.Guid)" />. /// <seealso cref="TryParse(string, out System.Guid)" />.
/// </summary> /// </summary>
/// <param name="value">A valid Squid encoded string.</param> /// <param name="value">A valid Squid encoded string.</param>
/// <returns>A new <see cref="System.Guid" /> object from the parsed string.</returns> /// <returns>A new <see cref="System.Guid" /> object from the parsed string.</returns>
public static Guid DecodeSquid(string value) public static Guid DecodeSquid(string value)
{ {
if (value == null) return Empty; if (value == null) return Empty;
value = value value = value
.Replace("_", "/") .Replace("_", "/")
.Replace("-", "+"); .Replace("-", "+");
var blob = Convert.FromBase64String(value + "=="); var blob = Convert.FromBase64String(value + "==");
return new Guid(blob); return new Guid(blob);
} }
/// <summary> /// <summary>
/// Squid to Guid. /// Squid to Guid.
/// </summary> /// </summary>
/// <param name="obj">A valid Squid object.</param> /// <param name="obj">A valid Squid object.</param>
/// <returns>System.Guid object.</returns> /// <returns>System.Guid object.</returns>
public static Guid FromSquid(Squid obj) public static Guid FromSquid(Squid obj)
{ {
return obj.Guid; return obj.Guid;
} }
/// <summary> /// <summary>
/// String to Squid. /// String to Squid.
/// </summary> /// </summary>
/// <param name="value">String value to convert</param> /// <param name="value">String value to convert</param>
/// <returns>A Squid object.</returns> /// <returns>A Squid object.</returns>
public static Squid FromString(string value) public static Squid FromString(string value)
{ {
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
return Empty; return Empty;
return TryParse(value, out Squid obj) ? obj : Empty; return TryParse(value, out Squid obj) ? obj : Empty;
} }
/// <summary> /// <summary>
/// Decodes the given value to a <see cref="System.Guid" />. /// Decodes the given value to a <see cref="System.Guid" />.
/// </summary> /// </summary>
/// <param name="value">The Squid encoded string to decode.</param> /// <param name="value">The Squid encoded string to decode.</param>
/// <param name="obj">A new <see cref="System.Guid" /> object from the parsed string.</param> /// <param name="obj">A new <see cref="System.Guid" /> object from the parsed string.</param>
/// <returns>A boolean indicating if the decode was successful.</returns> /// <returns>A boolean indicating if the decode was successful.</returns>
public static bool TryDecode(string value, out Guid obj) public static bool TryDecode(string value, out Guid obj)
{ {
try try
{ {
// Decode as Squid // Decode as Squid
obj = DecodeSquid(value); obj = DecodeSquid(value);
return true; return true;
} }
#pragma warning disable CA1031 // Do not catch general exception types #pragma warning disable CA1031 // Do not catch general exception types
catch (Exception) catch (Exception)
#pragma warning restore CA1031 // Do not catch general exception types #pragma warning restore CA1031 // Do not catch general exception types
{ {
// Return empty Guid // Return empty Guid
obj = Guid.Empty; obj = Guid.Empty;
return false; return false;
} }
} }
/// <summary> /// <summary>
/// Tries to parse the given string value and /// Tries to parse the given string value and
/// outputs the <see cref="Squid" /> object. /// outputs the <see cref="Squid" /> object.
/// </summary> /// </summary>
/// <param name="value">The Squid encoded string or string representation of a Guid.</param> /// <param name="value">The Squid encoded string or string representation of a Guid.</param>
/// <param name="obj">A new <see cref="Squid" /> object from the parsed string.</param> /// <param name="obj">A new <see cref="Squid" /> object from the parsed string.</param>
/// <returns>A boolean indicating if the parse was successful.</returns> /// <returns>A boolean indicating if the parse was successful.</returns>
public static bool TryParse(string value, out Squid obj) public static bool TryParse(string value, out Squid obj)
{ {
// Parse as Squid string. // Parse as Squid string.
if (TryDecode(value, out var oGuid)) if (TryDecode(value, out var oGuid))
{ {
obj = oGuid; obj = oGuid;
return true; return true;
} }
// Parse as Guid string. // Parse as Guid string.
if (Guid.TryParse(value, out oGuid)) if (Guid.TryParse(value, out oGuid))
{ {
obj = oGuid; obj = oGuid;
return true; return true;
} }
obj = Empty; obj = Empty;
return false; return false;
} }
/// <summary> /// <summary>
/// Tries to parse the string value and /// Tries to parse the string value and
/// outputs the underlying <see cref="System.Guid" /> object. /// outputs the underlying <see cref="System.Guid" /> object.
/// </summary> /// </summary>
/// <param name="value">The Squid encoded string or string representation of a Guid.</param> /// <param name="value">The Squid encoded string or string representation of a Guid.</param>
/// <param name="obj">A new <see cref="System.Guid" /> object from the parsed string.</param> /// <param name="obj">A new <see cref="System.Guid" /> object from the parsed string.</param>
/// <returns>A boolean indicating if the parse was successful.</returns> /// <returns>A boolean indicating if the parse was successful.</returns>
public static bool TryParse(string value, out Guid obj) public static bool TryParse(string value, out Guid obj)
{ {
// Try a Squid string. // Try a Squid string.
if (TryDecode(value, out obj)) if (TryDecode(value, out obj))
return true; return true;
// Try a Guid string. // Try a Guid string.
if (Guid.TryParse(value, out obj)) if (Guid.TryParse(value, out obj))
return true; return true;
obj = Guid.Empty; obj = Guid.Empty;
return false; return false;
} }
#region Operators #region Operators
/// <summary> /// <summary>
/// Determines if both Squid objects have the same /// Determines if both Squid objects have the same
/// underlying <see cref="System.Guid" /> value. /// underlying <see cref="System.Guid" /> value.
/// </summary> /// </summary>
/// <param name="x">The x.</param> /// <param name="x">The x.</param>
/// <param name="y">The y.</param> /// <param name="y">The y.</param>
/// <returns>The result of the operator.</returns> /// <returns>The result of the operator.</returns>
public static bool operator ==(Squid x, Squid y) public static bool operator ==(Squid x, Squid y)
{ {
return x.Guid == y.Guid; return x.Guid == y.Guid;
} }
/// <summary> /// <summary>
/// Determines if both objects have the same /// Determines if both objects have the same
/// underlying <see cref="System.Guid" /> value. /// underlying <see cref="System.Guid" /> value.
/// </summary> /// </summary>
/// <param name="x">The x.</param> /// <param name="x">The x.</param>
/// <param name="y">The y.</param> /// <param name="y">The y.</param>
/// <returns>The result of the operator.</returns> /// <returns>The result of the operator.</returns>
public static bool operator ==(Squid x, Guid y) public static bool operator ==(Squid x, Guid y)
{ {
return x.Guid == y; return x.Guid == y;
} }
/// <summary> /// <summary>
/// Determines if both objects have the same /// Determines if both objects have the same
/// underlying <see cref="System.Guid" /> value. /// underlying <see cref="System.Guid" /> value.
/// </summary> /// </summary>
/// <param name="x">The x.</param> /// <param name="x">The x.</param>
/// <param name="y">The y.</param> /// <param name="y">The y.</param>
/// <returns>The result of the operator.</returns> /// <returns>The result of the operator.</returns>
public static bool operator ==(Guid x, Squid y) public static bool operator ==(Guid x, Squid y)
{ {
return y == x; // NB: order of arguments return y == x; // NB: order of arguments
} }
/// <summary> /// <summary>
/// Determines if both Squid objects do not have the same /// Determines if both Squid objects do not have the same
/// underlying <see cref="System.Guid" /> value. /// underlying <see cref="System.Guid" /> value.
/// </summary> /// </summary>
/// <param name="x">The x.</param> /// <param name="x">The x.</param>
/// <param name="y">The y.</param> /// <param name="y">The y.</param>
/// <returns>The result of the operator.</returns> /// <returns>The result of the operator.</returns>
public static bool operator !=(Squid x, Squid y) public static bool operator !=(Squid x, Squid y)
{ {
return !(x == y); return !(x == y);
} }
/// <summary> /// <summary>
/// Determines if both objects do not have the same /// Determines if both objects do not have the same
/// underlying <see cref="System.Guid" /> value. /// underlying <see cref="System.Guid" /> value.
/// </summary> /// </summary>
/// <param name="x">The x.</param> /// <param name="x">The x.</param>
/// <param name="y">The y.</param> /// <param name="y">The y.</param>
/// <returns>The result of the operator.</returns> /// <returns>The result of the operator.</returns>
public static bool operator !=(Squid x, Guid y) public static bool operator !=(Squid x, Guid y)
{ {
return !(x == y); return !(x == y);
} }
/// <summary> /// <summary>
/// Determines if both objects do not have the same /// Determines if both objects do not have the same
/// underlying <see cref="System.Guid" /> value. /// underlying <see cref="System.Guid" /> value.
/// </summary> /// </summary>
/// <param name="x">The x.</param> /// <param name="x">The x.</param>
/// <param name="y">The y.</param> /// <param name="y">The y.</param>
/// <returns>The result of the operator.</returns> /// <returns>The result of the operator.</returns>
public static bool operator !=(Guid x, Squid y) public static bool operator !=(Guid x, Squid y)
{ {
return !(x == y); return !(x == y);
} }
/// <summary> /// <summary>
/// Implicitly converts the Squid to /// Implicitly converts the Squid to
/// its string equivalent. /// its string equivalent.
/// </summary> /// </summary>
/// <param name="oSquid">The o squid.</param> /// <param name="oSquid">The o squid.</param>
/// <returns>The result of the conversion.</returns> /// <returns>The result of the conversion.</returns>
public static implicit operator string(Squid oSquid) public static implicit operator string(Squid oSquid)
{ {
return oSquid.Value; return oSquid.Value;
} }
/// <summary> /// <summary>
/// Implicitly converts the Squid to /// Implicitly converts the Squid to
/// its <see cref="System.Guid" /> equivalent. /// its <see cref="System.Guid" /> equivalent.
/// </summary> /// </summary>
/// <param name="oSquid">The o squid.</param> /// <param name="oSquid">The o squid.</param>
/// <returns>The result of the conversion.</returns> /// <returns>The result of the conversion.</returns>
public static implicit operator Guid(Squid oSquid) public static implicit operator Guid(Squid oSquid)
{ {
return oSquid.Guid; return oSquid.Guid;
} }
/// <summary> /// <summary>
/// Implicitly converts the string to a Squid. /// Implicitly converts the string to a Squid.
/// </summary> /// </summary>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <returns>The result of the conversion.</returns> /// <returns>The result of the conversion.</returns>
public static implicit operator Squid(string value) public static implicit operator Squid(string value)
{ {
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
return Empty; return Empty;
return TryParse(value, out Squid oSquid) ? oSquid : Empty; return TryParse(value, out Squid oSquid) ? oSquid : Empty;
} }
/// <summary> /// <summary>
/// Implicitly converts the <see cref="System.Guid" /> to a Squid. /// Implicitly converts the <see cref="System.Guid" /> to a Squid.
/// </summary> /// </summary>
/// <param name="oGuid">The o unique identifier.</param> /// <param name="oGuid">The o unique identifier.</param>
/// <returns>The result of the conversion.</returns> /// <returns>The result of the conversion.</returns>
public static implicit operator Squid(Guid oGuid) public static implicit operator Squid(Guid oGuid)
{ {
return oGuid == Guid.Empty ? Empty : new Squid(oGuid); return oGuid == Guid.Empty ? Empty : new Squid(oGuid);
} }
#endregion #endregion
} }
} }

View file

@ -1,76 +1,76 @@
// *********************************************************************** // ***********************************************************************
// Assembly : FCS.Lib.Utility // Assembly : FCS.Lib.Utility
// Author : FH // Author : FH
// Created : 2020-09-09 // Created : 2020-09-09
// //
// Last Modified By : FH // Last Modified By : FH
// Last Modified On : 03-14-2022 // Last Modified On : 03-14-2022
// *********************************************************************** // ***********************************************************************
// <copyright file="StringOptions.cs" company="FCS"> // <copyright file="StringOptions.cs" company="FCS">
// Copyright (C) 2022 FCS Frede's Computer Services. // Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as // it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the // published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version. // License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details. // GNU Affero General Public License for more details.
// //
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses] // along with this program. If not, see [https://www.gnu.org/licenses]
// </copyright> // </copyright>
// <summary></summary> // <summary></summary>
// *********************************************************************** // ***********************************************************************
namespace FCS.Lib.Utility namespace FCS.Lib.Utility
{ {
/// <summary> /// <summary>
/// Class StringOptions. /// Class StringOptions.
/// </summary> /// </summary>
public class StringOptions public class StringOptions
{ {
/// <summary> /// <summary>
/// Gets or sets the required length of a string /// Gets or sets the required length of a string
/// </summary> /// </summary>
/// <value>The length of the required.</value> /// <value>The length of the required.</value>
public int RequiredLength { get; set; } public int RequiredLength { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to [require non letter or digit]. /// Gets or sets a value indicating whether to [require non letter or digit].
/// </summary> /// </summary>
/// <value><c>true</c> if [require non letter or digit]; otherwise, <c>false</c>.</value> /// <value><c>true</c> if [require non letter or digit]; otherwise, <c>false</c>.</value>
public bool RequireNonLetterOrDigit { get; set; } public bool RequireNonLetterOrDigit { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to [require digit]. /// Gets or sets a value indicating whether to [require digit].
/// </summary> /// </summary>
/// <value><c>true</c> if [require digit]; otherwise, <c>false</c>.</value> /// <value><c>true</c> if [require digit]; otherwise, <c>false</c>.</value>
public bool RequireDigit { get; set; } public bool RequireDigit { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to [require lowercase]. /// Gets or sets a value indicating whether to [require lowercase].
/// </summary> /// </summary>
/// <value><c>true</c> if [require lowercase]; otherwise, <c>false</c>.</value> /// <value><c>true</c> if [require lowercase]; otherwise, <c>false</c>.</value>
public bool RequireLowercase { get; set; } public bool RequireLowercase { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to [require uppercase]. /// Gets or sets a value indicating whether to [require uppercase].
/// </summary> /// </summary>
/// <value><c>true</c> if [require uppercase]; otherwise, <c>false</c>.</value> /// <value><c>true</c> if [require uppercase]; otherwise, <c>false</c>.</value>
public bool RequireUppercase { get; set; } public bool RequireUppercase { get; set; }
/// <summary> /// <summary>
/// Gets or sets the required unique chars. /// Gets or sets the required unique chars.
/// </summary> /// </summary>
/// <value>The required unique chars.</value> /// <value>The required unique chars.</value>
public int RequiredUniqueChars { get; set; } public int RequiredUniqueChars { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether to [require non alphanumeric]. /// Gets or sets a value indicating whether to [require non alphanumeric].
/// </summary> /// </summary>
/// <value><c>true</c> if [require non alphanumeric]; otherwise, <c>false</c>.</value> /// <value><c>true</c> if [require non alphanumeric]; otherwise, <c>false</c>.</value>
public bool RequireNonAlphanumeric { get; set; } public bool RequireNonAlphanumeric { get; set; }
} }
} }

View file

@ -1,233 +1,233 @@
// *********************************************************************** // ***********************************************************************
// Assembly : FCS.Lib.Utility // Assembly : FCS.Lib.Utility
// Author : FH // Author : FH
// Created : 03-30-2022 // Created : 03-30-2022
// //
// Last Modified By : FH // Last Modified By : FH
// Last Modified On : 04-19-2022 // Last Modified On : 04-19-2022
// *********************************************************************** // ***********************************************************************
// <copyright file="VatFormatValidator.cs" company="FCS"> // <copyright file="VatFormatValidator.cs" company="FCS">
// Copyright (C) 2022 FCS Frede's Computer Services. // Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as // it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the // published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version. // License, or (at your option) any later version.
// //
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details. // GNU Affero General Public License for more details.
// //
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses] // along with this program. If not, see [https://www.gnu.org/licenses]
// </copyright> // </copyright>
// <summary></summary> // <summary></summary>
// *********************************************************************** // ***********************************************************************
using System.Linq; using System.Linq;
namespace FCS.Lib.Utility namespace FCS.Lib.Utility
{ {
/// <summary> /// <summary>
/// Vat format validator /// Vat format validator
/// </summary> /// </summary>
public static class VatFormatValidator public static class VatFormatValidator
{ {
// https://ec.europa.eu/taxation_customs/vies/faqvies.do#item_11 // https://ec.europa.eu/taxation_customs/vies/faqvies.do#item_11
// https://ec.europa.eu/taxation_customs/vies/ // https://ec.europa.eu/taxation_customs/vies/
/// <summary> /// <summary>
/// Check vat number format /// Check vat number format
/// </summary> /// </summary>
/// <param name="countryCode"></param> /// <param name="countryCode"></param>
/// <param name="vatNumber"></param> /// <param name="vatNumber"></param>
/// <returns>bool indicating if the vat number conform to country specification</returns> /// <returns>bool indicating if the vat number conform to country specification</returns>
public static bool CheckVat(string countryCode, string vatNumber) public static bool CheckVat(string countryCode, string vatNumber)
{ {
return countryCode.ToUpperInvariant() switch return countryCode.ToUpperInvariant() switch
{ {
"DK" => ValidateFormatDk(vatNumber), "DK" => ValidateFormatDk(vatNumber),
"NO" => ValidateFormatNo(vatNumber), "NO" => ValidateFormatNo(vatNumber),
"SE" => ValidateFormatSe(vatNumber), "SE" => ValidateFormatSe(vatNumber),
_ => false _ => false
}; };
} }
/// <summary> /// <summary>
/// sanitize vat number /// sanitize vat number
/// </summary> /// </summary>
/// <param name="vatNumber"></param> /// <param name="vatNumber"></param>
/// <returns>sanitized string</returns> /// <returns>sanitized string</returns>
public static string SanitizeVatNumber(string vatNumber) public static string SanitizeVatNumber(string vatNumber)
{ {
vatNumber = vatNumber.ToUpperInvariant(); vatNumber = vatNumber.ToUpperInvariant();
return vatNumber return vatNumber
.Replace(" ", "") .Replace(" ", "")
.Replace("-", "") .Replace("-", "")
.Replace("_", "") .Replace("_", "")
.Replace("DK", "") .Replace("DK", "")
.Replace("NO", "") .Replace("NO", "")
.Replace("SE","") .Replace("SE","")
.Replace("MVA", ""); .Replace("MVA", "");
} }
private static bool ValidateFormatDk(string vatNumber) private static bool ValidateFormatDk(string vatNumber)
{ {
// https://wiki.scn.sap.com/wiki/display/CRM/Denmark // https://wiki.scn.sap.com/wiki/display/CRM/Denmark
// 8 digits 0 to 9 // 8 digits 0 to 9
// C1..C7 // C1..C7
// C8 check-digit MOD11 // C8 check-digit MOD11
// C1 > 0 // C1 > 0
// R = (2*C1 + 7*C2 + 6*C3 + 5*C4 + 4*C5 + 3*C6 + 2*C7 + C8) // R = (2*C1 + 7*C2 + 6*C3 + 5*C4 + 4*C5 + 3*C6 + 2*C7 + C8)
if(vatNumber.Length == 8 && long.TryParse(vatNumber, out _)) if(vatNumber.Length == 8 && long.TryParse(vatNumber, out _))
return ValidateMod11(vatNumber); return ValidateMod11(vatNumber);
return false; return false;
} }
private static bool ValidateFormatNo(string vatNumber) private static bool ValidateFormatNo(string vatNumber)
{ {
// https://wiki.scn.sap.com/wiki/display/CRM/Norway // https://wiki.scn.sap.com/wiki/display/CRM/Norway
// 12 digits // 12 digits
// C1..C8 random 0 to 9 // C1..C8 random 0 to 9
// C9 check-digit MOD11 // C9 check-digit MOD11
// C10 C11 C12 chars == MVA // C10 C11 C12 chars == MVA
try try
{ {
if (vatNumber.Length == 9 && long.TryParse(vatNumber, out _)) if (vatNumber.Length == 9 && long.TryParse(vatNumber, out _))
return ValidateMod11(vatNumber); return ValidateMod11(vatNumber);
return false; return false;
} }
catch catch
{ {
return false; return false;
} }
} }
private static bool ValidateFormatSe(string vatNumber) private static bool ValidateFormatSe(string vatNumber)
{ {
// https://wiki.scn.sap.com/wiki/display/CRM/Sweden // https://wiki.scn.sap.com/wiki/display/CRM/Sweden
// 12 digits 0 to 9 // 12 digits 0 to 9
// C10 = (10 (18 + 5 + 1 + 8 + 4)MOD10 10) MOD10 // C10 = (10 (18 + 5 + 1 + 8 + 4)MOD10 10) MOD10
// R = S1 + S3 + S5 + S7 + S9 // R = S1 + S3 + S5 + S7 + S9
// Si = int(Ci/5) + (Ci*2)MOD10) // Si = int(Ci/5) + (Ci*2)MOD10)
// https://www.skatteverket.se/skatter/mervardesskattmoms/momsregistreringsnummer.4.18e1b10334ebe8bc80002649.html // https://www.skatteverket.se/skatter/mervardesskattmoms/momsregistreringsnummer.4.18e1b10334ebe8bc80002649.html
// C11 C12 == 01 (De två sista siffrorna är alltid 01) // C11 C12 == 01 (De två sista siffrorna är alltid 01)
if (vatNumber.Length != 12 || vatNumber.Substring(10) != "01" || !long.TryParse(vatNumber, out _)) if (vatNumber.Length != 12 || vatNumber.Substring(10) != "01" || !long.TryParse(vatNumber, out _))
return false; return false;
var r = new[] { 0, 2, 4, 6, 8 } var r = new[] { 0, 2, 4, 6, 8 }
.Sum(m => (int)char.GetNumericValue(vatNumber[m]) / 5 + .Sum(m => (int)char.GetNumericValue(vatNumber[m]) / 5 +
(int)char.GetNumericValue(vatNumber[m]) * 2 % 10); (int)char.GetNumericValue(vatNumber[m]) * 2 % 10);
var c1 = new[] { 1, 3, 5, 7 }.Sum(m => (int)char.GetNumericValue(vatNumber[m])); var c1 = new[] { 1, 3, 5, 7 }.Sum(m => (int)char.GetNumericValue(vatNumber[m]));
var c10 = (10 - (r + c1) % 10) % 10; var c10 = (10 - (r + c1) % 10) % 10;
return $"{vatNumber.Substring(0, 9)}{c10}01" == vatNumber; return $"{vatNumber.Substring(0, 9)}{c10}01" == vatNumber;
} }
private static bool ValidateMod11(string number) private static bool ValidateMod11(string number)
{ {
try try
{ {
if (long.Parse(number) == 0) if (long.Parse(number) == 0)
return false; return false;
var sum = 0; var sum = 0;
for (int i = number.Length - 1, multiplier = 1; i >= 0; i--) for (int i = number.Length - 1, multiplier = 1; i >= 0; i--)
{ {
// Console.WriteLine($"char: {number[i]} multiplier: {multiplier}"); // Console.WriteLine($"char: {number[i]} multiplier: {multiplier}");
sum += (int)char.GetNumericValue(number[i]) * multiplier; sum += (int)char.GetNumericValue(number[i]) * multiplier;
if (++multiplier > 7) multiplier = 2; if (++multiplier > 7) multiplier = 2;
} }
return sum % 11 == 0; return sum % 11 == 0;
} }
catch catch
{ {
return false; return false;
} }
} }
//private static bool ValidateMod10(string number) //private static bool ValidateMod10(string number)
//{ //{
// if (long.Parse(number) == 0) // if (long.Parse(number) == 0)
// return false; // return false;
// var nDigits = number.Length; // var nDigits = number.Length;
// var nSum = 0; // var nSum = 0;
// var isSecond = false; // var isSecond = false;
// for (var i = nDigits - 1; i >= 0; i--) // for (var i = nDigits - 1; i >= 0; i--)
// { // {
// var d = (int)char.GetNumericValue(number[i]) - '0'; // var d = (int)char.GetNumericValue(number[i]) - '0';
// if (isSecond) // if (isSecond)
// d *= 2; // d *= 2;
// nSum += d / 10; // nSum += d / 10;
// nSum += d % 10; // nSum += d % 10;
// isSecond = !isSecond; // isSecond = !isSecond;
// } // }
// return nSum % 10 == 0; // return nSum % 10 == 0;
//} //}
//private static string GetMod10CheckDigit(string number) //private static string GetMod10CheckDigit(string number)
//{ //{
// var sum = 0; // var sum = 0;
// var alt = true; // var alt = true;
// var digits = number.ToCharArray(); // var digits = number.ToCharArray();
// for (var i = digits.Length - 1; i >= 0; i--) // for (var i = digits.Length - 1; i >= 0; i--)
// { // {
// var curDigit = digits[i] - 48; // var curDigit = digits[i] - 48;
// if (alt) // if (alt)
// { // {
// curDigit *= 2; // curDigit *= 2;
// if (curDigit > 9) // if (curDigit > 9)
// curDigit -= 9; // curDigit -= 9;
// } // }
// sum += curDigit; // sum += curDigit;
// alt = !alt; // alt = !alt;
// } // }
// return sum % 10 == 0 ? "0" : (10 - sum % 10).ToString(); // return sum % 10 == 0 ? "0" : (10 - sum % 10).ToString();
//} //}
//private string AddMod11CheckDigit(string number) //private string AddMod11CheckDigit(string number)
//{ //{
// return number + GetMod11CheckDigit(number); // return number + GetMod11CheckDigit(number);
//} //}
//private static string GetMod11CheckDigit(string number) //private static string GetMod11CheckDigit(string number)
//{ //{
// var sum = 0; // var sum = 0;
// for (int i = number.Length - 1, multiplier = 2; i >= 0; i--) // for (int i = number.Length - 1, multiplier = 2; i >= 0; i--)
// { // {
// sum += (int)char.GetNumericValue(number[i]) * multiplier; // sum += (int)char.GetNumericValue(number[i]) * multiplier;
// if (++multiplier > 7) multiplier = 2; // if (++multiplier > 7) multiplier = 2;
// } // }
// var modulo = sum % 11; // var modulo = sum % 11;
// return modulo is 0 or 1 ? "0" : (11 - modulo).ToString(); // return modulo is 0 or 1 ? "0" : (11 - modulo).ToString();
//} //}
//private static bool CheckLuhn(string vatNumber) //private static bool CheckLuhn(string vatNumber)
//{ //{
// // https://www.geeksforgeeks.org/luhn-algorithm/ // // https://www.geeksforgeeks.org/luhn-algorithm/
// var nDigits = vatNumber.Length; // var nDigits = vatNumber.Length;
// var nSum = 0; // var nSum = 0;
// var isSecond = false; // var isSecond = false;
// for (var i = nDigits - 1; i >= 0; i--) // for (var i = nDigits - 1; i >= 0; i--)
// { // {
// var d = (int)char.GetNumericValue(vatNumber[i]) - '0'; // var d = (int)char.GetNumericValue(vatNumber[i]) - '0';
// if (isSecond) // if (isSecond)
// d *= 2; // d *= 2;
// // We add two digits to handle // // We add two digits to handle
// // cases that make two digits // // cases that make two digits
// // after doubling // // after doubling
// nSum += d / 10; // nSum += d / 10;
// nSum += d % 10; // nSum += d % 10;
// isSecond = !isSecond; // isSecond = !isSecond;
// } // }
// return nSum % 10 == 0; // return nSum % 10 == 0;
//} //}
} }
} }