(feature): init
This commit is contained in:
commit
8ac380c7d4
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
262
.gitignore
vendored
Normal file
262
.gitignore
vendored
Normal file
@ -0,0 +1,262 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# DNX
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
#*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignoreable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
orleans.codegen.cs
|
||||
.directory
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush
|
||||
.cr/
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
197
README.md
Normal file
197
README.md
Normal file
@ -0,0 +1,197 @@
|
||||
# MaksIT.Core
|
||||
|
||||
MaksIT.Core is a collection of helper methods and extensions for .NET projects, designed to simplify common tasks and improve code readability. The library includes extensions for `Guid`, `string`, `Object`, and a base class for creating enumeration types.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Usage](#usage)
|
||||
- [Enumeration](#enumeration)
|
||||
- [Guid Extensions](#guid-extensions)
|
||||
- [Object Extensions](#object-extensions)
|
||||
- [String Extensions](#string-extensions)
|
||||
- [Available Methods](#available-methods)
|
||||
- [Enumeration Methods](#enumeration-methods)
|
||||
- [Guid Methods](#guid-methods)
|
||||
- [Object Methods](#object-methods)
|
||||
- [String Methods](#string-methods)
|
||||
- [Contributing](#contributing)
|
||||
- [License](#license)
|
||||
|
||||
## Installation
|
||||
|
||||
To install MaksIT.Core, add the package to your project via NuGet:
|
||||
|
||||
```sh
|
||||
dotnet add package MaksIT.Core
|
||||
```
|
||||
|
||||
Or manually add it to your `.csproj` file:
|
||||
|
||||
```xml
|
||||
<PackageReference Include="MaksIT.Core" Version="1.0.0" />
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Enumeration
|
||||
|
||||
The `Enumeration` base class provides a way to create strongly-typed enums in C#. This is useful for scenarios where you need more functionality than the default `enum` type.
|
||||
|
||||
**Example:**
|
||||
|
||||
```csharp
|
||||
public class Status : Enumeration
|
||||
{
|
||||
public static readonly Status Active = new Status(1, "Active");
|
||||
public static readonly Status Inactive = new Status(2, "Inactive");
|
||||
|
||||
private Status(int id, string name) : base(id, name) { }
|
||||
}
|
||||
|
||||
// Usage
|
||||
var activeStatus = Status.FromValue<Status>(1);
|
||||
Console.WriteLine(activeStatus.Name); // Output: Active
|
||||
```
|
||||
|
||||
### Guid Extensions
|
||||
|
||||
The `GuidExtensions` class contains extensions for working with `Guid` types.
|
||||
|
||||
**Example:**
|
||||
|
||||
```csharp
|
||||
Guid guid = Guid.NewGuid();
|
||||
Guid? nullableGuid = guid.ToNullable();
|
||||
```
|
||||
|
||||
### Object Extensions
|
||||
|
||||
The `ObjectExtensions` class provides extensions for working with objects.
|
||||
|
||||
**Example:**
|
||||
|
||||
```csharp
|
||||
var person = new { Name = "John", Age = 30 };
|
||||
string json = person.ToJson();
|
||||
Console.WriteLine(json); // Output: {"name":"John","age":30}
|
||||
```
|
||||
|
||||
### String Extensions
|
||||
|
||||
The `StringExtensions` class provides a variety of useful string manipulation methods.
|
||||
|
||||
**Example:**
|
||||
|
||||
```csharp
|
||||
string text = "Hello World";
|
||||
bool isLike = text.Like("Hello*"); // SQL-like matching
|
||||
Console.WriteLine(isLike); // Output: True
|
||||
```
|
||||
|
||||
## Available Methods
|
||||
|
||||
### Enumeration Methods
|
||||
|
||||
- **`GetAll<T>()`**: Retrieves all static fields of a given type `T` that derive from `Enumeration`.
|
||||
- **`Equals(object? obj)`**: Determines whether the specified object is equal to the current object.
|
||||
- **`GetHashCode()`**: Returns the hash code for the current object.
|
||||
- **`AbsoluteDifference(Enumeration firstValue, Enumeration secondValue)`**: Computes the absolute difference between two enumeration values.
|
||||
- **`FromValue<T>(int value)`**: Retrieves an instance of type `T` from its integer value.
|
||||
- **`FromDisplayName<T>(string displayName)`**: Retrieves an instance of type `T` from its display name.
|
||||
- **`CompareTo(object? other)`**: Compares the current instance with another object of the same type.
|
||||
|
||||
### Guid Methods
|
||||
|
||||
- **`ToNullable(this Guid id)`**: Converts a `Guid` to a nullable `Guid?`. Returns `null` if the `Guid` is `Guid.Empty`.
|
||||
|
||||
### Object Methods
|
||||
|
||||
- **`ToJson<T>(this T? obj)`**: Converts an object to a JSON string using default serialization options.
|
||||
- **`ToJson<T>(this T? obj, List<JsonConverter>? converters)`**: Converts an object to a JSON string using custom converters.
|
||||
|
||||
### String Methods
|
||||
|
||||
- **`Like(this string? text, string? wildcardedText)`**: Determines if a string matches a given wildcard pattern (SQL LIKE).
|
||||
- **`Left(this string s, int count)`**: Returns the left substring of the specified length.
|
||||
- **`Right(this string s, int count)`**: Returns the right substring of the specified length.
|
||||
- **`Mid(this string s, int index, int count)`**: Returns a substring starting from the specified index with the specified length.
|
||||
- **`ToInteger(this string s)`**: Converts a string to an integer, returning zero if conversion fails.
|
||||
- **`IsInteger(this string s)`**: Determines whether the string represents an integer.
|
||||
- **`Prepend(this StringBuilder sb, string content)`**: Prepends content to the beginning of a `StringBuilder`.
|
||||
- **`ToEnum<T>(this string input)`**: Converts a string to an enum value of type `T`.
|
||||
- **`ToNullableEnum<T>(this string input)`**: Converts a string to a nullable enum value of type `T`.
|
||||
- **`ToNull(this string s)`**: Returns `null` if the string is empty or whitespace.
|
||||
- **`NullIfEmptyString(this string s)`**: Returns `null` if the string is empty or whitespace, otherwise returns the original string.
|
||||
- **`ToLong(this string s)`**: Converts a string to a long, returning a hash code if conversion fails.
|
||||
- **`ToNullableLong(this string s)`**: Converts a string to a nullable long, returning `null` if conversion fails.
|
||||
- **`ToInt(this string s)`**: Converts a string to an int, returning a hash code if conversion fails.
|
||||
- **`ToNullableInt(this string s)`**: Converts a string to a nullable int, returning `null` if conversion fails.
|
||||
- **`ToUint(this string s)`**: Converts a string to a uint, returning a hash code if conversion fails.
|
||||
- **`ToNullableUint(this string s)`**: Converts a string to a nullable uint, returning `null` if conversion fails.
|
||||
- **`ToDecimal(this string s)`**: Converts a string to a decimal, returning a hash code if conversion fails.
|
||||
- **`ToNullableDecimal(this string s)`**: Converts a string to a nullable decimal, returning `null` if conversion fails.
|
||||
- **`ToDouble(this string s)`**: Converts a string to a double, returning a hash code if conversion fails.
|
||||
- **`ToNullableDouble(this string s)`**: Converts a string to a nullable double, returning `null` if conversion fails.
|
||||
- **`ToDate(this string s, string[] formats)`**: Converts a string to a `DateTime` object using a specified format.
|
||||
- **`ToDate(this string s)`**: Converts a string to a `DateTime` object using the default format.
|
||||
- **`ToNullableDate(this string s)`**: Converts a string to a nullable `DateTime` object using the default format.
|
||||
- **`ToNullableDate(this string s, string[] formats)`**: Converts a string to a nullable `DateTime` object using specified formats.
|
||||
- **`ToDateTime(this string s, string[] formats)`**: Converts a string to a `DateTime` object using specified formats.
|
||||
- **`ToDateTime(this string s)`**: Converts a string to a `DateTime` object using the default formats.
|
||||
- **`ToNullableDateTime(this string s)`**: Converts a string to a nullable `DateTime` object using the default formats.
|
||||
- **`ToNullableDateTime(this string s, string[] formats)`**: Converts a string to a nullable `DateTime` object using specified formats.
|
||||
- **`ToBool(this string s)`**: Converts a string to a boolean.
|
||||
- **`ToNullableBool(this string s)`**: Converts a string to a nullable boolean.
|
||||
- **`ToGuid(this string text)`**: Converts a string to a `Guid`.
|
||||
- **`ToNullableGuid(this string s)`**: Converts a string to a nullable `Guid`.
|
||||
- **`StringSplit(this string s, char c)`**: Splits a string by a specified character and trims each resulting element.
|
||||
- **`ToTitle(this string s)`**: Converts the first character of the string to uppercase.
|
||||
- **`ExtractUrls(this string s)`**: Extracts all URLs from a string.
|
||||
- **`Format(this string s, params object[] args)`**: Formats a string using specified arguments.
|
||||
- **`Excerpt(this string s, int length = 60)`**: Truncates a string to a specified length, adding ellipses if necessary.
|
||||
- **`ToObject<T>(this string s)`**: Deserializes a JSON string into an object of type `T`.
|
||||
- **`ToObject<T>(this string s, List<JsonConverter> converters)`**: Deserializes a JSON string into an object of type `T` using custom converters.
|
||||
- **`IsValidEmail(this string? s)`**: Validates whether the string is a valid email format.
|
||||
- **`HtmlToPlainText(this string htmlCode)`**: Converts HTML content to plain text.
|
||||
- **`ToCamelCase(this string input)`**: Converts a string to camel case.
|
||||
|
||||
## Contribution
|
||||
|
||||
Contributions to this project are welcome! Please fork the repository and submit a pull request with your changes. If you encounter any issues or have feature requests, feel free to open an issue on GitHub.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License. See the full license text below.
|
||||
|
||||
---
|
||||
|
||||
### MIT License
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Maksym Sadovnychyy (MAKS-IT)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
## Contact
|
||||
|
||||
For any questions or inquiries, please reach out via GitHub or [email](mailto:maksym.sadovnychyy@gmail.com).
|
||||
165
src/MaksIT.Core.Tests/Abstractions/EnumerationTests.cs
Normal file
165
src/MaksIT.Core.Tests/Abstractions/EnumerationTests.cs
Normal file
@ -0,0 +1,165 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace MaksIT.Core.Abstractions.Tests {
|
||||
|
||||
public class TestEnumeration : Enumeration {
|
||||
public static readonly TestEnumeration First = new TestEnumeration(1, "First");
|
||||
public static readonly TestEnumeration Second = new TestEnumeration(2, "Second");
|
||||
public static readonly TestEnumeration Third = new TestEnumeration(3, "Third");
|
||||
|
||||
public TestEnumeration(int id, string name) : base(id, name) { }
|
||||
}
|
||||
|
||||
|
||||
public class EnumerationTests {
|
||||
[Fact]
|
||||
public void GetAll_ShouldReturnAllEnumerations() {
|
||||
// Act
|
||||
var allValues = Enumeration.GetAll<TestEnumeration>().ToList();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(allValues);
|
||||
Assert.Equal(3, allValues.Count);
|
||||
Assert.Contains(TestEnumeration.First, allValues);
|
||||
Assert.Contains(TestEnumeration.Second, allValues);
|
||||
Assert.Contains(TestEnumeration.Third, allValues);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1, "First")]
|
||||
[InlineData(2, "Second")]
|
||||
[InlineData(3, "Third")]
|
||||
public void FromValue_ShouldReturnEnumerationByValue(int id, string expectedName) {
|
||||
// Act
|
||||
var result = Enumeration.FromValue<TestEnumeration>(id);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(expectedName, result.Name);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("First", 1)]
|
||||
[InlineData("Second", 2)]
|
||||
[InlineData("Third", 3)]
|
||||
public void FromDisplayName_ShouldReturnEnumerationByName(string displayName, int expectedId) {
|
||||
// Act
|
||||
var result = Enumeration.FromDisplayName<TestEnumeration>(displayName);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(expectedId, result.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AbsoluteDifference_ShouldReturnCorrectDifference() {
|
||||
// Act
|
||||
var difference = Enumeration.AbsoluteDifference(TestEnumeration.First, TestEnumeration.Third);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, difference);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Equals_SameReference_ShouldReturnTrue() {
|
||||
// Act
|
||||
var result = TestEnumeration.First.Equals(TestEnumeration.First);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Equals_DifferentReferencesSameValues_ShouldReturnTrue() {
|
||||
// Arrange
|
||||
var firstCopy = Enumeration.FromValue<TestEnumeration>(1);
|
||||
|
||||
// Act
|
||||
var result = TestEnumeration.First.Equals(firstCopy);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Equals_DifferentValues_ShouldReturnFalse() {
|
||||
// Act
|
||||
var result = TestEnumeration.First.Equals(TestEnumeration.Second);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CompareTo_ShouldReturnZeroForEqualValues() {
|
||||
// Arrange
|
||||
var firstCopy = Enumeration.FromValue<TestEnumeration>(1);
|
||||
|
||||
// Act
|
||||
var result = TestEnumeration.First.CompareTo(firstCopy);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CompareTo_ShouldReturnPositiveForGreaterValue() {
|
||||
// Act
|
||||
var result = TestEnumeration.Second.CompareTo(TestEnumeration.First);
|
||||
|
||||
// Assert
|
||||
Assert.True(result > 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CompareTo_ShouldReturnNegativeForLesserValue() {
|
||||
// Act
|
||||
var result = TestEnumeration.First.CompareTo(TestEnumeration.Second);
|
||||
|
||||
// Assert
|
||||
Assert.True(result < 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CompareTo_InvalidComparison_ShouldThrowArgumentException() {
|
||||
// Arrange
|
||||
var nonEnumerationObject = new object();
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentException>(() => TestEnumeration.First.CompareTo(nonEnumerationObject));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetHashCode_ShouldReturnIdHashCode() {
|
||||
// Act
|
||||
var hashCode = TestEnumeration.First.GetHashCode();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(TestEnumeration.First.Id.GetHashCode(), hashCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToString_ShouldReturnName() {
|
||||
// Act
|
||||
var result = TestEnumeration.First.ToString();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("First", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_InvalidValue_ShouldThrowInvalidOperationException() {
|
||||
// Act & Assert
|
||||
Assert.Throws<InvalidOperationException>(() => Enumeration.FromValue<TestEnumeration>(999));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_InvalidDisplayName_ShouldThrowInvalidOperationException() {
|
||||
// Act & Assert
|
||||
Assert.Throws<InvalidOperationException>(() => Enumeration.FromDisplayName<TestEnumeration>("NonExistent"));
|
||||
}
|
||||
}
|
||||
}
|
||||
72
src/MaksIT.Core.Tests/Extensions/GuidExtensionsTests.cs
Normal file
72
src/MaksIT.Core.Tests/Extensions/GuidExtensionsTests.cs
Normal file
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace MaksIT.Core.Extensions.Tests {
|
||||
public class GuidExtensionsTests {
|
||||
[Fact]
|
||||
public void ToNullable_WithEmptyGuid_ShouldReturnNull() {
|
||||
// Arrange
|
||||
var emptyGuid = Guid.Empty;
|
||||
|
||||
// Act
|
||||
var result = emptyGuid.ToNullable();
|
||||
|
||||
// Assert
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToNullable_WithNonEmptyGuid_ShouldReturnSameGuid() {
|
||||
// Arrange
|
||||
var nonEmptyGuid = Guid.NewGuid();
|
||||
|
||||
// Act
|
||||
var result = nonEmptyGuid.ToNullable();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(nonEmptyGuid, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToNullable_WithDefaultGuid_ShouldReturnNull() {
|
||||
// Arrange
|
||||
var defaultGuid = default(Guid);
|
||||
|
||||
// Act
|
||||
var result = defaultGuid.ToNullable();
|
||||
|
||||
// Assert
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToNullable_WithSameGuidTwice_ShouldReturnSameGuidEachTime() {
|
||||
// Arrange
|
||||
var guid = Guid.NewGuid();
|
||||
|
||||
// Act
|
||||
var result1 = guid.ToNullable();
|
||||
var result2 = guid.ToNullable();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(result1, result2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToNullable_WithMultipleNewGuids_ShouldReturnUniqueNonEmptyResults() {
|
||||
// Arrange
|
||||
var guid1 = Guid.NewGuid();
|
||||
var guid2 = Guid.NewGuid();
|
||||
|
||||
// Act
|
||||
var result1 = guid1.ToNullable();
|
||||
var result2 = guid2.ToNullable();
|
||||
|
||||
// Assert
|
||||
Assert.NotEqual(result1, result2);
|
||||
Assert.NotNull(result1);
|
||||
Assert.NotNull(result2);
|
||||
}
|
||||
}
|
||||
}
|
||||
122
src/MaksIT.Core.Tests/Extensions/ObjectExtensionsTests.cs
Normal file
122
src/MaksIT.Core.Tests/Extensions/ObjectExtensionsTests.cs
Normal file
@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using MaksIT.Core.Extensions;
|
||||
using Xunit;
|
||||
|
||||
namespace MaksIT.Core.Tests.Extensions {
|
||||
public class ObjectExtensionsTests {
|
||||
private class TestObject {
|
||||
public required string Name { get; set; }
|
||||
public int Age { get; set; }
|
||||
public string? Address { get; set; }
|
||||
}
|
||||
|
||||
private class CustomDateTimeConverter : JsonConverter<DateTime> {
|
||||
private readonly string _format;
|
||||
|
||||
public CustomDateTimeConverter(string format) {
|
||||
_format = format;
|
||||
}
|
||||
|
||||
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
|
||||
var dateString = reader.GetString();
|
||||
if (dateString is null) {
|
||||
throw new JsonException("Expected a date string but got null.");
|
||||
}
|
||||
|
||||
return DateTime.ParseExact(dateString, _format, null);
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) {
|
||||
writer.WriteStringValue(value.ToString(_format));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToJson_WithNullObject_ShouldReturnEmptyJson() {
|
||||
// Arrange
|
||||
TestObject? obj = null;
|
||||
|
||||
// Act
|
||||
var result = obj.ToJson();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("{}", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToJson_WithSimpleObject_ShouldReturnCorrectJson() {
|
||||
// Arrange
|
||||
var obj = new TestObject {
|
||||
Name = "John Doe",
|
||||
Age = 30
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = obj.ToJson();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("{\"name\":\"John Doe\",\"age\":30}", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToJson_WithObjectAndNullValues_ShouldIgnoreNullProperties() {
|
||||
// Arrange
|
||||
var obj = new TestObject {
|
||||
Name = "John Doe",
|
||||
Age = 30,
|
||||
Address = null
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = obj.ToJson();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("{\"name\":\"John Doe\",\"age\":30}", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToJson_WithCustomJsonConverter_ShouldApplyConverter() {
|
||||
// Arrange
|
||||
var obj = new DateTime(2023, 08, 30);
|
||||
var converters = new List<JsonConverter> { new CustomDateTimeConverter("yyyy-MM-dd") };
|
||||
|
||||
// Act
|
||||
var result = obj.ToJson(converters);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("\"2023-08-30\"", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToJson_WithComplexObjectAndConverters_ShouldSerializeCorrectly() {
|
||||
// Arrange
|
||||
var obj = new {
|
||||
Name = "Jane Doe",
|
||||
BirthDate = new DateTime(1990, 12, 25)
|
||||
};
|
||||
|
||||
var converters = new List<JsonConverter> { new CustomDateTimeConverter("yyyy/MM/dd") };
|
||||
|
||||
// Act
|
||||
var result = obj.ToJson(converters);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("{\"name\":\"Jane Doe\",\"birthDate\":\"1990/12/25\"}", result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToJson_WithEmptyObject_ShouldReturnEmptyJsonObject() {
|
||||
// Arrange
|
||||
var obj = new { };
|
||||
|
||||
// Act
|
||||
var result = obj.ToJson();
|
||||
|
||||
// Assert
|
||||
Assert.Equal("{}", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
244
src/MaksIT.Core.Tests/Extensions/StringExtensionsTests.cs
Normal file
244
src/MaksIT.Core.Tests/Extensions/StringExtensionsTests.cs
Normal file
@ -0,0 +1,244 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using MaksIT.Core.Extensions;
|
||||
using Xunit;
|
||||
|
||||
namespace MaksIT.Core.Tests.Extensions {
|
||||
public class StringExtensionsTests {
|
||||
[Theory]
|
||||
[InlineData("Hello World", "H*", true)] // Match starts with 'H'
|
||||
[InlineData("Hello World", "h*", true)] // Case insensitive match
|
||||
[InlineData("Hello World", "*World", true)] // Match ends with 'World'
|
||||
[InlineData("Hello World", "Hello?World", true)] // '?' should match exactly one character (space in this case)
|
||||
[InlineData("Hello World", "*W?rld", true)] // '?' matches 'o' in 'World'
|
||||
[InlineData("Hello World", "Goodbye*", false)] // No match for 'Goodbye*'
|
||||
public void Like_ShouldReturnExpectedResults(string input, string pattern, bool expected) {
|
||||
// Act
|
||||
bool result = input.Like(pattern);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("abcdef", 3, "abc")]
|
||||
[InlineData("abcdef", 0, "")]
|
||||
[InlineData("abcdef", 10, "abcdef")]
|
||||
public void Left_ShouldReturnLeftSubstring(string input, int count, string expected) {
|
||||
// Act
|
||||
string result = input.Left(count);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("abcdef", 3, "def")]
|
||||
[InlineData("abcdef", 0, "")]
|
||||
[InlineData("abcdef", 10, "abcdef")]
|
||||
public void Right_ShouldReturnRightSubstring(string input, int count, string expected) {
|
||||
// Act
|
||||
string result = input.Right(count);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("abcdef", 1, 3, "bcd")]
|
||||
[InlineData("abcdef", 0, 2, "ab")]
|
||||
[InlineData("abcdef", 4, 10, "ef")]
|
||||
[InlineData("abcdef", 6, 2, "")]
|
||||
public void Mid_ShouldReturnSubstring(string input, int index, int count, string expected) {
|
||||
// Act
|
||||
string result = input.Mid(index, count);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("123", 123)]
|
||||
[InlineData("abc", 0)]
|
||||
[InlineData(null, 0)]
|
||||
[InlineData("", 0)]
|
||||
public void ToInteger_ShouldConvertToInteger(string input, int expected) {
|
||||
// Act
|
||||
int result = input.ToInteger();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("123", true)]
|
||||
[InlineData("-123", true)]
|
||||
[InlineData("abc", false)]
|
||||
[InlineData("123abc", false)]
|
||||
public void IsInteger_ShouldReturnIfStringIsInteger(string input, bool expected) {
|
||||
// Act
|
||||
bool result = input.IsInteger();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Prepend_ShouldPrependStringToStringBuilder() {
|
||||
// Arrange
|
||||
var sb = new StringBuilder("World");
|
||||
string content = "Hello ";
|
||||
|
||||
// Act
|
||||
sb.Prepend(content);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("Hello World", sb.ToString());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1", DayOfWeek.Monday)]
|
||||
[InlineData("Tuesday", DayOfWeek.Tuesday)]
|
||||
[InlineData("5", DayOfWeek.Friday)]
|
||||
public void ToEnum_ShouldConvertStringToEnum(string input, DayOfWeek expected) {
|
||||
// Act
|
||||
DayOfWeek result = input.ToEnum<DayOfWeek>();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToEnum_InvalidValue_ShouldThrowNotSupportedException() {
|
||||
// Arrange
|
||||
string input = "NotAnEnumValue";
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<NotSupportedException>(() => input.ToEnum<DayOfWeek>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(" ", null)]
|
||||
[InlineData("", null)]
|
||||
[InlineData("valid", "valid")]
|
||||
public void ToNull_ShouldReturnNullForWhitespaceOrEmptyString(string input, string expected) {
|
||||
// Act
|
||||
var result = input.ToNull();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("123", 123L)]
|
||||
public void ToLong_ShouldConvertToLong_WhenValidLong(string input, long? expected) {
|
||||
// Act
|
||||
var result = input.ToLong();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("abc", null)]
|
||||
[InlineData("", null)]
|
||||
public void ToLong_ShouldReturnNull_WhenInvalidLong(string input, long? expected) {
|
||||
// Act
|
||||
var result = input.ToLong();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("2021-08-30", new[] { "yyyy-MM-dd" }, "2021-08-30T00:00:00Z")]
|
||||
[InlineData("30/08/2021", new[] { "dd/MM/yyyy" }, "2021-08-30T00:00:00Z")]
|
||||
public void ToDate_ShouldConvertToDate(string input, string[] formats, string expected) {
|
||||
// Act
|
||||
var result = input.ToDate(formats);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(DateTime.Parse(expected, null, DateTimeStyles.RoundtripKind), result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("2021-08-30T00:00:00Z", "2021-08-30T00:00:00Z")]
|
||||
[InlineData("Now", "Now")]
|
||||
public void ToDateTime_ShouldConvertToDateTime(string input, string expected) {
|
||||
// Act
|
||||
var result = input.ToDateTime();
|
||||
|
||||
// Assert
|
||||
if (expected == "Now") {
|
||||
Assert.Equal(DateTime.Now.ToString("dd/MM/yyyy"), result.ToString("dd/MM/yyyy"));
|
||||
}
|
||||
else {
|
||||
Assert.Equal(DateTime.Parse(expected, null, DateTimeStyles.RoundtripKind), result);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("ok", true)]
|
||||
[InlineData("yes", true)]
|
||||
[InlineData("true", true)]
|
||||
[InlineData("1", true)]
|
||||
[InlineData("no", false)]
|
||||
[InlineData("false", false)]
|
||||
[InlineData("0", false)]
|
||||
[InlineData("invalid", false)]
|
||||
public void ToBool_ShouldConvertToBool(string input, bool expected) {
|
||||
// Act
|
||||
var result = input.ToBool();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("e02fd0e4-00fd-090A-ca30-0d00a0038ba0", "e02fd0e4-00fd-090a-ca30-0d00a0038ba0")]
|
||||
[InlineData("invalid-guid", null)]
|
||||
public void ToGuid_ShouldConvertStringToGuid(string input, string expected) {
|
||||
// Act
|
||||
if (expected == null) {
|
||||
var result = input.ToGuid();
|
||||
|
||||
// Assert that it returns a valid Guid (from MD5 hash, not an exception)
|
||||
Assert.IsType<Guid>(result);
|
||||
Assert.NotEqual(Guid.Empty, result); // Check that it does not return Guid.Empty
|
||||
}
|
||||
else {
|
||||
var result = input.ToGuid();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(Guid.Parse(expected), result);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("<p>Hello World</p>", "Hello World")]
|
||||
[InlineData("<script>alert('test');</script><p>Hello</p>", "Hello")]
|
||||
public void HtmlToPlainText_ShouldConvertHtmlToPlainText(string input, string expected) {
|
||||
// Act
|
||||
var result = input.HtmlToPlainText();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("hello world", "helloWorld")]
|
||||
[InlineData("Hello World", "helloWorld")]
|
||||
[InlineData("HELLO_WORLD", "helloWorld")]
|
||||
[InlineData("HELLO-WORLD", "helloWorld")]
|
||||
public void ToCamelCase_ShouldConvertToCamelCase(string input, string expected) {
|
||||
// Act
|
||||
var result = input.ToCamelCase();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
src/MaksIT.Core.Tests/MaksIT.Core.Tests.csproj
Normal file
27
src/MaksIT.Core.Tests/MaksIT.Core.Tests.csproj
Normal file
@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="xunit" Version="2.5.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MaksIT.Core\MaksIT.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
31
src/MaksIT.Core.sln
Normal file
31
src/MaksIT.Core.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.002.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaksIT.Core", "MaksIT.Core\MaksIT.Core.csproj", "{4AE39520-D4F7-4C5F-ACE9-9E79AEAF3228}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaksIT.Core.Tests", "MaksIT.Core.Tests\MaksIT.Core.Tests.csproj", "{B67A43DA-AFFC-4510-8D51-08F1FF84CC5B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4AE39520-D4F7-4C5F-ACE9-9E79AEAF3228}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4AE39520-D4F7-4C5F-ACE9-9E79AEAF3228}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4AE39520-D4F7-4C5F-ACE9-9E79AEAF3228}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4AE39520-D4F7-4C5F-ACE9-9E79AEAF3228}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B67A43DA-AFFC-4510-8D51-08F1FF84CC5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B67A43DA-AFFC-4510-8D51-08F1FF84CC5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B67A43DA-AFFC-4510-8D51-08F1FF84CC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B67A43DA-AFFC-4510-8D51-08F1FF84CC5B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {9BCC72D1-8BE8-4924-AF73-C8E86E16EC59}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
50
src/MaksIT.Core/Abstractions/Enumeration.cs
Normal file
50
src/MaksIT.Core/Abstractions/Enumeration.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace MaksIT.Core.Abstractions {
|
||||
public abstract class Enumeration : IComparable {
|
||||
public string Name { get; }
|
||||
|
||||
public int Id { get; }
|
||||
|
||||
protected Enumeration(int id, string name) => (Id, Name) = (id, name);
|
||||
|
||||
public override string ToString() => Name;
|
||||
|
||||
public static IEnumerable<T> GetAll<T>() where T : Enumeration =>
|
||||
typeof(T).GetFields(BindingFlags.Public |
|
||||
BindingFlags.Static |
|
||||
BindingFlags.DeclaredOnly)
|
||||
.Select(f => f.GetValue(null))
|
||||
.Cast<T>();
|
||||
|
||||
public override bool Equals(object? obj) =>
|
||||
obj is Enumeration otherValue &&
|
||||
GetType() == obj.GetType() &&
|
||||
Id == otherValue.Id;
|
||||
|
||||
public override int GetHashCode() => Id.GetHashCode();
|
||||
|
||||
public static int AbsoluteDifference(Enumeration firstValue, Enumeration secondValue) =>
|
||||
Math.Abs(firstValue.Id - secondValue.Id);
|
||||
|
||||
public static T FromValue<T>(int value) where T : Enumeration =>
|
||||
Parse<T, int>(value, nameof(value), item => item.Id == value);
|
||||
|
||||
public static T FromDisplayName<T>(string displayName) where T : Enumeration =>
|
||||
Parse<T, string>(displayName, nameof(displayName), item => item.Name == displayName);
|
||||
|
||||
private static T Parse<T, TK>(TK value, string description, Func<T, bool> predicate) where T : Enumeration =>
|
||||
GetAll<T>().FirstOrDefault(predicate) ??
|
||||
throw new InvalidOperationException($"'{value}' is not a valid {description} in {typeof(T)}");
|
||||
|
||||
public int CompareTo(object? other) {
|
||||
if (other is Enumeration otherEnumeration)
|
||||
return Id.CompareTo(otherEnumeration.Id);
|
||||
else
|
||||
throw new ArgumentException($"Object is not of type {nameof(Enumeration)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
15
src/MaksIT.Core/Extensions/GuidExtensions.cs
Normal file
15
src/MaksIT.Core/Extensions/GuidExtensions.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MaksIT.Core.Extensions {
|
||||
public static class GuidExtensions {
|
||||
public static Guid? ToNullable(this Guid id) {
|
||||
// Return null if the Guid is the default value (Guid.Empty)
|
||||
return id == default ? null : id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
36
src/MaksIT.Core/Extensions/ObjectExtensions.cs
Normal file
36
src/MaksIT.Core/Extensions/ObjectExtensions.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MaksIT.Core.Extensions;
|
||||
|
||||
public static class ObjectExtensions {
|
||||
|
||||
/// <summary>
|
||||
/// Converts object to json string
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToJson<T>(this T? obj) => obj.ToJson(null);
|
||||
|
||||
/// <summary>
|
||||
/// Converts object to json string
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="obj"></param>
|
||||
/// <param name="converters"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToJson<T>(this T? obj, List<JsonConverter>? converters) {
|
||||
if (obj == null)
|
||||
return "{}";
|
||||
|
||||
var options = new JsonSerializerOptions {
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
};
|
||||
|
||||
converters?.ForEach(x => options.Converters.Add(x));
|
||||
|
||||
return JsonSerializer.Serialize(obj, options);
|
||||
}
|
||||
}
|
||||
232
src/MaksIT.Core/Extensions/StringExtensions.cs
Normal file
232
src/MaksIT.Core/Extensions/StringExtensions.cs
Normal file
@ -0,0 +1,232 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace MaksIT.Core.Extensions {
|
||||
public static partial class StringExtensions {
|
||||
/// <summary>
|
||||
/// SQL Like implementation using wildcard patterns.
|
||||
/// </summary>
|
||||
public static bool Like(this string? text, string? wildcardedText) {
|
||||
if (text is null || wildcardedText is null) return false;
|
||||
|
||||
return Regex.IsMatch(text, wildcardedText.WildcardToRegular(), RegexOptions.IgnoreCase | RegexOptions.Multiline);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a wildcarded string to a regular expression.
|
||||
/// </summary>
|
||||
private static string WildcardToRegular(this string value) =>
|
||||
$"^{Regex.Escape(value).Replace("\\?", ".").Replace("\\*", ".*")}$";
|
||||
|
||||
/// <summary>
|
||||
/// Returns the left substring of the specified length.
|
||||
/// </summary>
|
||||
public static string Left(this string s, int count) =>
|
||||
s.Substring(0, Math.Min(count, s.Length));
|
||||
|
||||
/// <summary>
|
||||
/// Returns the right substring of the specified length.
|
||||
/// </summary>
|
||||
public static string Right(this string s, int count) =>
|
||||
s.Substring(Math.Max(0, s.Length - count));
|
||||
|
||||
/// <summary>
|
||||
/// Returns a substring starting from the specified index with the specified length.
|
||||
/// </summary>
|
||||
public static string Mid(this string s, int index, int count) =>
|
||||
s.Substring(index, Math.Min(count, s.Length - index));
|
||||
|
||||
/// <summary>
|
||||
/// Converts the string to an integer, returning zero if conversion fails.
|
||||
/// </summary>
|
||||
public static int ToInteger(this string s) =>
|
||||
int.TryParse(s, out var integerValue) ? integerValue : 0;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the string represents an integer.
|
||||
/// </summary>
|
||||
public static bool IsInteger(this string s) => Regex.IsMatch(s, @"^-?\d+$");
|
||||
|
||||
public static StringBuilder Prepend(this StringBuilder sb, string content) => sb.Insert(0, content);
|
||||
|
||||
public static T ToEnum<T>(this string input) where T : struct {
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
throw new ArgumentException("Input cannot be null or empty.", nameof(input));
|
||||
|
||||
if (Enum.TryParse(input, true, out T result))
|
||||
return result;
|
||||
|
||||
var enumType = typeof(T);
|
||||
|
||||
foreach (T enumItem in Enum.GetValues(enumType)) {
|
||||
var att = enumType.GetMember(enumItem.ToString() ?? string.Empty)[0]
|
||||
.GetCustomAttributes(typeof(DisplayAttribute), false)
|
||||
.SingleOrDefault() as DisplayAttribute;
|
||||
|
||||
var displayName = att?.GetName();
|
||||
|
||||
if (input.Equals(displayName, StringComparison.InvariantCultureIgnoreCase))
|
||||
return enumItem;
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"Cannot parse the value '{input}' for {enumType}");
|
||||
}
|
||||
|
||||
public static T? ToNullableEnum<T>(this string input) where T : struct =>
|
||||
!string.IsNullOrWhiteSpace(input) ? input.ToEnum<T>() : null;
|
||||
|
||||
public static string? ToNull(this string s) => string.IsNullOrWhiteSpace(s) ? null : s;
|
||||
|
||||
public static string? NullIfEmptyString(this string s) => s.ToNull();
|
||||
|
||||
public static long? ToLong(this string s) =>
|
||||
long.TryParse(s, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out var result) ? result : (long?)null;
|
||||
|
||||
public static long? ToNullableLong(this string s) => string.IsNullOrWhiteSpace(s) ? (long?)null : s.ToLong();
|
||||
|
||||
public static int? ToInt(this string s) =>
|
||||
int.TryParse(s, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out var result) ? result : (int?)null;
|
||||
|
||||
public static int? ToNullableInt(this string s) => string.IsNullOrWhiteSpace(s) ? (int?)null : s.ToInt();
|
||||
|
||||
public static uint? ToUint(this string s) =>
|
||||
uint.TryParse(s, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out var result) ? result : (uint?)null;
|
||||
|
||||
public static uint? ToNullableUint(this string s) => string.IsNullOrWhiteSpace(s) ? (uint?)null : s.ToUint();
|
||||
|
||||
public static decimal? ToDecimal(this string s) =>
|
||||
decimal.TryParse(s, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out var result) ? result : (decimal?)null;
|
||||
|
||||
public static decimal? ToNullableDecimal(this string s) => string.IsNullOrWhiteSpace(s) ? (decimal?)null : s.ToDecimal();
|
||||
|
||||
public static double? ToDouble(this string s) =>
|
||||
double.TryParse(s, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out var result) ? result : (double?)null;
|
||||
|
||||
public static double? ToNullableDouble(this string s) => string.IsNullOrWhiteSpace(s) ? (double?)null : s.ToDouble();
|
||||
|
||||
#region DateTime
|
||||
public static DateTime ToDate(this string s, string[] formats) =>
|
||||
DateTime.TryParseExact(s, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out var datetime)
|
||||
? DateTime.SpecifyKind(datetime, DateTimeKind.Utc)
|
||||
: throw new FormatException($"The date [{s}] is not in the required format: [{formats[0]}]");
|
||||
|
||||
public static DateTime ToDate(this string s) => s.ToDate(new[] { "dd/MM/yyyy" });
|
||||
|
||||
public static DateTime? ToNullableDate(this string s) => string.IsNullOrEmpty(s) ? (DateTime?)null : s.ToDate();
|
||||
|
||||
public static DateTime? ToNullableDate(this string s, string[] formats) => string.IsNullOrEmpty(s) ? (DateTime?)null : s.ToDate(formats);
|
||||
|
||||
public static DateTime ToDateTime(this string s, string[] formats) {
|
||||
if (s.Equals("Now", StringComparison.OrdinalIgnoreCase)) return DateTime.Now;
|
||||
if (s.Equals("UtcNow", StringComparison.OrdinalIgnoreCase)) return DateTime.UtcNow;
|
||||
if (s.Equals("Today", StringComparison.OrdinalIgnoreCase)) return DateTime.Today;
|
||||
|
||||
return DateTime.TryParseExact(s, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result)
|
||||
? DateTime.SpecifyKind(result, DateTimeKind.Utc)
|
||||
: throw new FormatException($"Unable to parse exact date from value [{s}] with formats [{string.Join(", ", formats)}]");
|
||||
}
|
||||
|
||||
public static DateTime ToDateTime(this string s) => s.ToDateTime(new[] { "dd/MM/yyyy", "dd/MM/yyyy HH:mm:ss", "dd/MM/yyyy HH:mm", "yyyy-MM-dd'T'HH:mm:ss'Z'" });
|
||||
|
||||
public static DateTime? ToNullableDateTime(this string s) => string.IsNullOrWhiteSpace(s) ? (DateTime?)null : s.ToDateTime();
|
||||
|
||||
public static DateTime? ToNullableDateTime(this string s, string[] formats) => string.IsNullOrWhiteSpace(s) ? (DateTime?)null : s.ToDateTime(formats);
|
||||
#endregion
|
||||
|
||||
public static bool ToBool(this string s) =>
|
||||
new[] { "ok", "yes", "y", "true", "1" }.Contains(s, StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
public static bool? ToNullableBool(this string s) => string.IsNullOrWhiteSpace(s) ? (bool?)null : s.ToBool();
|
||||
|
||||
public static Guid ToGuid(this string text) =>
|
||||
Guid.TryParse(text, out var value) ? value : new Guid(MD5.Create().ComputeHash(Encoding.Default.GetBytes(text.ToUpper())));
|
||||
|
||||
public static Guid? ToNullableGuid(this string s) => string.IsNullOrWhiteSpace(s) ? (Guid?)null : s.ToGuid();
|
||||
|
||||
public static string[] StringSplit(this string s, char c) =>
|
||||
s.Split(c).Select(x => x.Trim()).ToArray();
|
||||
|
||||
public static string ToTitle(this string s) => string.IsNullOrWhiteSpace(s) ? s : char.ToUpper(s[0]) + s[1..];
|
||||
|
||||
[GeneratedRegex(@"(http|ftp|https):\\/\\/([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:\\/~+#-]*[\\w@?^=%&\\/~+#-])", RegexOptions.Compiled)]
|
||||
private static partial Regex UrlsRegex();
|
||||
|
||||
public static IEnumerable<Uri> ExtractUrls(this string s) =>
|
||||
UrlsRegex().Matches(s).Cast<Match>()
|
||||
.Select(match => match.Value)
|
||||
.Where(url => Uri.TryCreate(url, UriKind.Absolute, out _))
|
||||
.Select(url => new Uri(url))
|
||||
.Distinct();
|
||||
|
||||
public static string Format(this string s, params object[] args) => string.Format(s, args);
|
||||
|
||||
public static string Excerpt(this string s, int length = 60) =>
|
||||
string.IsNullOrWhiteSpace(s) ? s : s.Length <= length ? s : $"{s.Substring(0, length - 3)}...";
|
||||
|
||||
public static T? ToObject<T>(this string s) => ToObjectCore<T>(s, null);
|
||||
|
||||
public static T? ToObject<T>(this string s, List<JsonConverter> converters) => ToObjectCore<T>(s, converters);
|
||||
|
||||
private static T? ToObjectCore<T>(string s, List<JsonConverter>? converters) {
|
||||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
|
||||
converters?.ForEach(x => options.Converters.Add(x));
|
||||
return JsonSerializer.Deserialize<T>(s, options);
|
||||
}
|
||||
|
||||
public static bool IsValidEmail(this string? s) {
|
||||
if (s is null) return false;
|
||||
|
||||
const string pattern = @"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$";
|
||||
var regex = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture, TimeSpan.FromSeconds(2));
|
||||
|
||||
return regex.IsMatch(s);
|
||||
}
|
||||
|
||||
public static string HtmlToPlainText(this string htmlCode) {
|
||||
if (string.IsNullOrEmpty(htmlCode))
|
||||
return htmlCode;
|
||||
|
||||
var sb = new StringBuilder(htmlCode);
|
||||
|
||||
// Remove new lines, tabs, and multiple spaces
|
||||
sb.Replace("\n", " ").Replace("\t", " ");
|
||||
sb = new StringBuilder(Regex.Replace(sb.ToString(), "\\s+", " "));
|
||||
|
||||
// Remove <head> and <script> sections
|
||||
sb = new StringBuilder(Regex.Replace(sb.ToString(), "<head.*?</head>", "", RegexOptions.IgnoreCase | RegexOptions.Singleline));
|
||||
sb = new StringBuilder(Regex.Replace(sb.ToString(), "<script.*?</script>", "", RegexOptions.IgnoreCase | RegexOptions.Singleline));
|
||||
|
||||
// Replace HTML entities
|
||||
string[] oldWords = { " ", "&", """, "<", ">", "®", "©", "•", "™", "'" };
|
||||
string[] newWords = { " ", "&", "\"", "<", ">", "®", "©", "•", "™", "'" };
|
||||
for (int i = 0; i < oldWords.Length; i++) sb.Replace(oldWords[i], newWords[i]);
|
||||
|
||||
// Handle line breaks
|
||||
sb.Replace("<br>", "\n").Replace("<br ", "\n<br ").Replace("<p ", "\n<p ");
|
||||
|
||||
// Remove all HTML tags
|
||||
var plainText = Regex.Replace(sb.ToString(), "<[^>]*>", "").Trim();
|
||||
|
||||
return plainText;
|
||||
}
|
||||
|
||||
public static string ToCamelCase(this string input) {
|
||||
if (string.IsNullOrEmpty(input)) return input;
|
||||
|
||||
var words = input.Split(new[] { ' ', '-', '_' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
for (var i = 0; i < words.Length; i++) {
|
||||
words[i] = i == 0 ? words[i].ToLower() : char.ToUpper(words[i][0]) + words[i][1..].ToLower();
|
||||
}
|
||||
|
||||
return string.Join("", words);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/MaksIT.Core/MaksIT.Core.csproj
Normal file
26
src/MaksIT.Core/MaksIT.Core.csproj
Normal file
@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>MaksIT.$(MSBuildProjectName.Replace(" ", "_"))</RootNamespace>
|
||||
|
||||
<!-- NuGet package metadata -->
|
||||
<PackageId>MaksIT.Core</PackageId>
|
||||
<Version>1.0.0</Version>
|
||||
<Authors>Maksym Sadovnychyy</Authors>
|
||||
<Company>MAKS-IT</Company>
|
||||
<Product>MaksIT.Core</Product>
|
||||
<Description>MaksIT.Core is a collection of helper methods and extensions for .NET projects, designed to simplify common tasks and improve code readability. The library includes extensions for `Guid`, `string`, `Object`, and a base class for creating enumeration types.</Description>
|
||||
<PackageTags>dotnet;enumeration;string;guid;object;parsers;extensions</PackageTags>
|
||||
<RepositoryUrl>https://github.com/MAKS-IT-COM/maksit-core</RepositoryUrl>
|
||||
<License>MIT</License>
|
||||
<RequireLicenseAcceptance>false</RequireLicenseAcceptance>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="../../README.md" Pack="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
7
src/Release-NuGetPackage.bat
Normal file
7
src/Release-NuGetPackage.bat
Normal file
@ -0,0 +1,7 @@
|
||||
@echo off
|
||||
|
||||
REM Change directory to the location of the script
|
||||
cd /d %~dp0
|
||||
|
||||
REM Invoke the PowerShell script (Release-NuGetPackage.ps1) in the same directory
|
||||
powershell -ExecutionPolicy Bypass -File "%~dp0Release-NuGetPackage.ps1"
|
||||
46
src/Release-NuGetPackage.ps1
Normal file
46
src/Release-NuGetPackage.ps1
Normal file
@ -0,0 +1,46 @@
|
||||
# Retrieve the API key from the environment variable
|
||||
$apiKey = $env:NUGET_MAKS_IT
|
||||
if (-not $apiKey) {
|
||||
Write-Host "Error: API key not found in environment variable NUGET_MAKS_IT."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# NuGet source
|
||||
$nugetSource = "https://api.nuget.org/v3/index.json"
|
||||
|
||||
# Define paths
|
||||
$solutionDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$projectDir = "$solutionDir\MaksIT.Core"
|
||||
$outputDir = "$projectDir\bin\Release"
|
||||
|
||||
# Clean previous builds
|
||||
Write-Host "Cleaning previous builds..."
|
||||
dotnet clean $projectDir -c Release
|
||||
|
||||
# Build the project
|
||||
Write-Host "Building the project..."
|
||||
dotnet build $projectDir -c Release
|
||||
|
||||
# Pack the NuGet package
|
||||
Write-Host "Packing the project..."
|
||||
dotnet pack $projectDir -c Release --no-build
|
||||
|
||||
# Look for the .nupkg file
|
||||
$packageFile = Get-ChildItem -Path $outputDir -Filter "*.nupkg" -Recurse | Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
||||
|
||||
if ($packageFile) {
|
||||
Write-Host "Package created successfully: $($packageFile.FullName)"
|
||||
|
||||
# Push the package to NuGet
|
||||
Write-Host "Pushing the package to NuGet..."
|
||||
dotnet nuget push $packageFile.FullName -k $apiKey -s $nugetSource --skip-duplicate
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "Package pushed successfully."
|
||||
} else {
|
||||
Write-Host "Failed to push the package."
|
||||
}
|
||||
} else {
|
||||
Write-Host "Package creation failed. No .nupkg file found."
|
||||
exit 1
|
||||
}
|
||||
49
src/Release-NuGetPackage.sh
Normal file
49
src/Release-NuGetPackage.sh
Normal file
@ -0,0 +1,49 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Retrieve the API key from the environment variable
|
||||
apiKey=$NUGET_MAKS_IT
|
||||
if [ -z "$apiKey" ]; then
|
||||
echo "Error: API key not found in environment variable NUGET_MAKS_IT."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# NuGet source
|
||||
nugetSource="https://api.nuget.org/v3/index.json"
|
||||
|
||||
# Define paths
|
||||
scriptDir=$(dirname "$0")
|
||||
solutionDir=$(realpath "$scriptDir")
|
||||
projectDir="$solutionDir/MaksIT.Core"
|
||||
outputDir="$projectDir/bin/Release"
|
||||
|
||||
# Clean previous builds
|
||||
echo "Cleaning previous builds..."
|
||||
dotnet clean "$projectDir" -c Release
|
||||
|
||||
# Build the project
|
||||
echo "Building the project..."
|
||||
dotnet build "$projectDir" -c Release
|
||||
|
||||
# Pack the NuGet package
|
||||
echo "Packing the project..."
|
||||
dotnet pack "$projectDir" -c Release --no-build
|
||||
|
||||
# Look for the .nupkg file
|
||||
packageFile=$(find "$outputDir" -name "*.nupkg" -print0 | xargs -0 ls -t | head -n 1)
|
||||
|
||||
if [ -n "$packageFile" ]; then
|
||||
echo "Package created successfully: $packageFile"
|
||||
|
||||
# Push the package to NuGet
|
||||
echo "Pushing the package to NuGet..."
|
||||
dotnet nuget push "$packageFile" -k "$apiKey" -s "$nugetSource" --skip-duplicate
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Package pushed successfully."
|
||||
else
|
||||
echo "Failed to push the package."
|
||||
fi
|
||||
else
|
||||
echo "Package creation failed. No .nupkg file found."
|
||||
exit 1
|
||||
fi
|
||||
Loading…
Reference in New Issue
Block a user