Maestria.Extensions 3.3.1

.NET Standard 2.0
There is a newer version of this package available.
See the version list below for details.
dotnet add package Maestria.Extensions --version 3.3.1
NuGet\Install-Package Maestria.Extensions -Version 3.3.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Maestria.Extensions" Version="3.3.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Maestria.Extensions --version 3.3.1
#r "nuget: Maestria.Extensions, 3.3.1"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install Maestria.Extensions as a Cake Addin
#addin nuget:?package=Maestria.Extensions&version=3.3.1

// Install Maestria.Extensions as a Cake Tool
#tool nuget:?package=Maestria.Extensions&version=3.3.1

Maestria.Extensions

Build status NuGet MyGet Apimundo

Build History

donate

What is Maestria.Extensions?

Extension function pack to increase productivity and improve source code writing. By default, all extension methods are safe.

What is Maestria Project?

This library is part of Maestria Project.

Maestria is a project to provide productivity and elegance to your source code writing.

Where can I get it?

First, install NuGet. Then, install Maestria.Extensions from the package manager console:

PM> Install-Package Maestria.Extensions

or install from the dotnet cli command line:

> dotnet add package Maestria.Extensions

How do I get started?

First, import "Maestria.Extensions" reference:

using Maestria.Extensions;

Then in your application code, use fluent syntax

// AggregateExtenions
<Array>.Max();
<Array>.Min();

// Base64Extensions
<byte[]>.ToBase64(<byte[]>)
<string>.ToBase64(<string>, <Encoding>)

var decoded = <byte[]>.FromBase64(<encoded-byte[]>, <Encoding>)
var decoded = <string>.FromBase64(<encoded-string>, <Encoding>)

// CollectionExtensions
<IEnumerable>.IsNullOrEmpty()
<IEnumerable>.HasItems()
<IDictionary>.TryGetValue(<key>, <@default-value>)
<IEnumerable>.Iterate(item => <action>)
await <IEnumerable>.Iterate(async item => await <action>)
<IEnumerable>.Iterate((item, index) => <action>)
await <IEnumerable>.Iterate(async (item, index) => await <action>)

// EnumExtensions
<Enum>.GetDisplayName()
<Enum>.GetDescription()
EnumExtensions.GetValues<TEnum>()
EnumExtensions.GetValues(typeof(<TEnum>))

// ExceptionExtensions
<Exception>.GetAllMessages()
<Exception>.GetMostInner()

// HashExtensions
"value".GetHashMd5()
"value".GetHashSha1()
"value".GetHashSha256()
"value".GetHashSha384()
"value".GetHashSha512()
HashExtensions.ComputeHash(<HashAlgorithm>, "value")

// RoundExtensions
<floating-point>.Round(<digits>)
<floating-point>.Round(<digits>, <MidpointRounding>)
<floating-point>.RoundUp(<digits>)

// TruncateExtensions
<floating-point>.Truncate(<digits>)

// StringExtensions
<string>.TrimStart(<start-comparison>, <ignore-case>)
<string>.TrimEnd(<start-comparison>, <ignore-case>)
<string>.AddToBeginningIfNotStartsWith(<start-comparison>, <ignore-case>)
<string>.AddToBeginningIfHasValue(<start-comparison>, <prefix>)
<string>.AddToEndIfNotEndsWith(<start-comparison>, <ignore-case>)
<string>.AddToEndIfHasValue(<start-comparison>, <prefix>)
<string>.EscapeXml()
<string>.Format(<values-to-format>)
<string>.IsNullOrEmpty()
<string>.IsNullOrWhiteSpace()
<string>.EmptyIf(<string>)
<string>.EmptyIfNull()
<string>.EmptyIfNullOrWhiteSpace()
<string>.HasValue() // Check if text is not null and not white space
<string>.EqualsIgnoreCase(<camparison-value>, <auto-trim>)
<string>.OnlyNumbers()
<string>.RemoveAccents()
<string>.Join(<separator>)
<string>.SubstringBeforeFirstOccurrence("-")
<string>.SubstringBeforeLastOccurrence("-")
<string>.SubstringAfterFirstOccurrence("-")
<string>.SubstringAfterLastOccurrence("-")
<string>.SubstringAtOccurrenceIndex("-", 1)
<string>.SubstringSafe(<start-index>, <length>)
<string>.LimitLen(<length>)
<string>.LimitLenReverse(<length>)
<string>.OnlyLettersOrNumbersOrUnderscoresOrHyphensTest(<string>)
<string>.ToSnakeCase()

// Guid
<Guid>.IsEmpty()
<Guid?>.IsNullOrEmpty()
<string>.IsNullOrWhiteSpace()
<Guid>.IfEmpty(<value>)
<Guid?>.IfNullOrEmpty(<value>)

// SyntaxExtensions
<object>.IsNull()
<object>.HasValue() or <object>.IsNotNull() // Same result
<object>.In(<array-of-values>)
<IComparable>.Between(<starting-value>, <ending-value>)
<IComparable>.LimitMaxAt(<max-value>)
<IComparable>.LimitMinAt(<min-value>)

// Pipelines
var value = <string>
    .OnlyNumbers()
    .DetachedCall(x => Console.WriteLine(x)) // <<< Call a method with current value and continue execution pipeline
    .Format("mask"); // value is only the number of string formatted and only numbers are written on console

<string>
    .OnlyNumbers()
    .OutVar(out var variableToExternalFromScopeAccess) // <<< Create variable with current value on external scope and continua execution pipeline
    .Format("mask"); // value is only the number of string formatted and only numbers are written on console

If fluent expressions

It's possible to execute fluent comparisons expression with the syntax: <value>.IfGreater(<value-to-compare>).Then(<result-if-compare-is-true>).

The methods for comparison operations are: IfGreater, IfGreaterOrEqual, IfLest. IfLessOrEqual, If and IfNot.

Rules:

  • When condition it's false, result the pipeline is <value>.
  • When <value> or <value-to-compare> is null:
    • Result only true if both are null and comparison is equality operation If.
    • When an only value is null, the result is true if the operation is not equality comparison IfNot.
    • When <value> is Nullable<>, <result-if-compare-is-true> always if Nullable<> data type.
    • But when <value> is not Nullable<>, <result-if-compare-is-true> allow use Nullable<> and not Nullable<> data type.
    • All other operations comparisons result in false.
  • It's possible return null value at <result-if-compare-is-true>, but then indicated syntax is <value>.NullIf(<value-to-compare>).

Examples:

<IComparable>.IfGreater(10).Then(5)
<IComparable>.IfGreaterOrEqual(10).Then(5)
<IComparable>.IfLest(10).Then(5)
<IComparable>.IfLessOrEqual(10).Then(5)
<IComparable>.If(10).Then(5)
<IComparable>.IfNot(10).Then(5)

Delegates expression only executes when the condition it's true.

<IComparable>.IfGreater(10).Then(() => 5)
<IComparable>.IfGreaterOrEqual(10).Then(() => 5)
<IComparable>.IfLest(10).Then(() => 5)
<IComparable>.IfLessOrEqual(10).Then(() => 5)
<IComparable>.If(10).Then(() => 5)
<IComparable>.IfNot(10).Then(() => 5)

Other fluent comparison operations:

// IfNullExtensions
<object>.IfNull(<output-value-when-null>)
<string>.IfNullOrEmpty(<output-value-when-null-or-empty-string>)
<string>.IfNullOrWhiteSpace(<output-value-when-null-or-empty-white-space>)

// NullIfExtensions
<object>.NullIf(<comparison-value>)
<floating-point>.NullIf(<comparison-value>, <tolerance-to-comparasion>)

<string>.NullIf(<comparison-value>, <ignore-case>)
<string>.NullIfEmpty(<comparison-value>)
<string>.NullIfWhiteSpace(<comparison-value>)

<IComparable>.NullIfIn(<comparison-value>)
<IComparable>.NullIfBetween(<comparison-value>)

Data Types

ISimpleResult, SimpleResult and SimpleResult< TValue>

This structure has success and message for simple method result, extensible with generic TValue on "Value" property.

SimpleResult ok = SimpleResult.Ok(<optional-message>);
SimpleResult fail = SimpleResult.Fail("Fail message");

// Implict conversions
SimpleResult ok = true;
SimpleResult fail = "Fail message"
SimpleResult fail = new Exception("Fail message")


// Initializer
var result = new SimpleResult
{
    Success = true,
    Message = "Successfully processed"
}

To improve then development experience, there are implicit conversions to assign data from:

  • bool: To set or verify property Success.
  • string: To set fail message and Success to false.
  • Exception: To set fail message, Exception and Success to false.
  • TValue: To set value and Success to true (Even if null).

And implicit conversions to assingn data to:

  • bool:
    • SimpleResult: Get data from property Success.
    • SimpleResult<TValue>: Get data from property Success
  • Exception: Get data from property Exception
  • TValue: Get data from property Value

The property SuccessAndHasValue check if Success == true and Value != null in SimpleResult<TValue>.

Caution on SimpleResult<TValue>: Implicit comparison if (mySimpleResultVariable) is equivalent to if (mySimpleResultVariable.Success).
Use explicit if (mySimpleResultVariable.SuccessAndHasValue) when result value can be null with success is true

Use cases:

public SimpleResult Execute(Args args)
{
    if (args == null)
        return "Argument cannot be null";  // <===== Implicit cast to failure result
    try
    {
        // Execute actions
        return true; // <===== Implicit cast success result
    }
    catch (Exception e)
    {
        return e; // <===== Implicit cast to failure result
    }
}

public SimpleResult<int> Execute2(Args args)
{
    if (args == null)
        return "Argument cannot be null";  // <===== Implicit cast to failure result
    try
    {
        // Execute actions
        return 10; // <===== Implicit cast success result
    }
    catch (Exception e)
    {
        return e; // <===== Implicit cast to failure result
    }
}

// ...

var result = Execute(...);
var result2 = Execute2(...);

if (result && result2) // <===== Implicit cast to boolean
{
    // ...
}


Try<TSuccess, TFailure>

Auxiliary data type to increment the expressibility of method results when success and failure need different structures.
To facilitate development there is support for implicit conversion.

public void Try<PersonCreated, CustomError> Save(Person value) 
{
    ...
    if (condition)
        return new CustomError() { Code = 999, Message = "Failure message" }
    return new PersonCreated { Id = 123 };
}

...

var result = Save(person);
if (result)
    Console.WriteLine(result.Value.Id);
else
    Console.WriteLine($"Error {result.Failure.Code}: {result.Failure.Message}");

Settings

It's possible set default settings for library:

Extensions.GlobalSettings.Configure(cfg => cfg
    .FloatAndDoubleTolerance(default-float-and-double-comparasion-tolerance) // Default is 0.00001f

Development Guidelines

  • Create file with extensions method name
  • this argument name must be value for single object or values to IEnumerable inheritances
  • Put new file into folder /src/Extensions/<extended-data-type>
    • Expressions methods like If, NullIf, Is, In, EmptyIf, Between, must be located in src/Extensions/Comparable folder
    • Numbers extensions methods must bet located in src/Extensions/Number
  • The I prefix for interfaces must be omitted from the folder name.
  • src\Settings\MaestriaExtensionSettings: File to configure global defaults behaviors

buy-me-a-coffee smile.png

If my contributions helped you, please help me buy a coffee 😄

donate

Product Versions
.NET net5.0 net5.0-windows net6.0 net6.0-android net6.0-ios net6.0-maccatalyst net6.0-macos net6.0-tvos net6.0-windows net7.0 net7.0-android net7.0-ios net7.0-maccatalyst net7.0-macos net7.0-tvos net7.0-windows
.NET Core netcoreapp2.0 netcoreapp2.1 netcoreapp2.2 netcoreapp3.0 netcoreapp3.1
.NET Standard netstandard2.0 netstandard2.1
.NET Framework net461 net462 net463 net47 net471 net472 net48
MonoAndroid monoandroid
MonoMac monomac
MonoTouch monotouch
Tizen tizen40 tizen60
Xamarin.iOS xamarinios
Xamarin.Mac xamarinmac
Xamarin.TVOS xamarintvos
Xamarin.WatchOS xamarinwatchos
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
3.4.2 520 11/9/2022
3.4.1 69 11/9/2022
3.4.0 71 11/9/2022
3.3.2 821 10/7/2022
3.3.1 545 9/12/2022
3.3.0 163 9/12/2022
3.2.3 471 8/27/2022
3.2.2 156 8/26/2022
3.2.1 157 8/26/2022
3.2.0 1,946 5/31/2022
3.1.3 6,698 11/24/2021
3.1.2 379 11/3/2021
3.1.0 702 9/8/2021
3.0.2 228 9/8/2021
3.0.1 1,632 8/4/2021
3.0.0 279 8/4/2021
2.1.4 838 7/5/2021
2.1.3 430 6/22/2021
2.1.2 300 6/20/2021
2.1.1 317 6/7/2021
2.1.0 334 6/4/2021
2.0.13 242 6/1/2021
2.0.12 376 5/25/2021
2.0.11 248 5/20/2021
2.0.10 242 5/16/2021
2.0.9 226 5/4/2021
2.0.8 335 4/4/2021
2.0.7 209 4/3/2021
2.0.6 217 4/2/2021
2.0.5 233 3/28/2021
2.0.4 228 3/28/2021
2.0.3 260 3/27/2021
2.0.2 284 3/27/2021
2.0.1 302 3/19/2021
2.0.0 207 3/19/2021
1.2.5 322 3/14/2021
1.2.4 284 1/10/2021
1.2.3 283 1/10/2021
1.2.2 398 9/1/2020
1.2.1 335 8/14/2020
1.2.0 433 8/9/2020
1.1.1 414 7/28/2020
1.1.0 394 7/12/2020
1.0.10 339 4/19/2020
1.0.9 350 4/14/2020
1.0.8 345 4/14/2020
1.0.7 484 4/11/2020
1.0.6 479 12/20/2019
1.0.5 472 12/16/2019
1.0.4 394 12/16/2019
1.0.3 373 11/25/2019
1.0.2 355 11/18/2019
1.0.1 426 10/14/2019
1.0.0 410 10/9/2019