diff --git a/.gitignore b/.gitignore index 3fa5555..3ff42c7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ obj *.userprefs *.user *.sln.DotSettings.user +*.sln.ide # mstest test results TestResults diff --git a/BCLExtensions.nuspec b/BCLExtensions.nuspec index a950204..e5c322c 100644 --- a/BCLExtensions.nuspec +++ b/BCLExtensions.nuspec @@ -8,11 +8,12 @@ csmacnz https://github.com/csMACnz/BCLExtensions/blob/master/LICENSE https://github.com/csMACnz/BCLExtensions + http://img.csmac.nz/BCLExtensions.net-32.png false Base Class Library Extensions for C# base class library types like System.String. Base Class Library Extensions for C# base class library types like System.String. en-US Copyright 2015 - BCLExtensions, PCL, Extensions, Extension Methods, Helpers, Base Class Library + BCLExtensions PCL Extensions Extension Methods Helpers Portable Base Class Library diff --git a/README.md b/README.md index 0facac3..9cec30d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,19 @@ BCLExtensions ============= + + [![License](http://img.shields.io/:license-mit-blue.svg)](http://csmacnz.mit-license.org) [![NuGet](https://img.shields.io/nuget/v/BCLExtensions.svg)](https://www.nuget.org/packages/BCLExtensions) [![NuGet](https://img.shields.io/nuget/dt/BCLExtensions.svg)](https://www.nuget.org/packages/BCLExtensions) -[![Badges](http://img.shields.io/:badges-12/12-ff6799.svg)](https://github.com/badges/badgerbadgerbadger) +[![Gratipay](http://img.shields.io/gratipay/csMACnz.svg)](https://gratipay.com/csMACnz/) +[![Source Browser](https://img.shields.io/badge/Browse-Source-green.svg)](http://sourcebrowser.io/Browse/csMACnz/BCLExtensions) +[![Badges](http://img.shields.io/:badges-14/14-ff6799.svg)](https://github.com/badges/badgerbadgerbadger) + +[![Stories in Ready](https://badge.waffle.io/csmacnz/BCLExtensions.png?label=ready&title=Ready)](https://waffle.io/csmacnz/BCLExtensions) +[![Stories in progress](https://badge.waffle.io/csmacnz/BCLExtensions.png?label=in%20progress&title=In%20Progress)](https://waffle.io/csmacnz/BCLExtensions) +[![Issue Stats](http://www.issuestats.com/github/csMACnz/BCLExtensions/badge/pr)](http://www.issuestats.com/github/csMACnz/BCLExtensions) +[![Issue Stats](http://www.issuestats.com/github/csMACnz/BCLExtensions/badge/issue)](http://www.issuestats.com/github/csMACnz/BCLExtensions) [![AppVeyor Build status](https://img.shields.io/appveyor/ci/MarkClearwater/bclextensions.svg)](https://ci.appveyor.com/project/MarkClearwater/bclextensions) [![Travis Build Status](https://img.shields.io/travis/csMACnz/BCLExtensions.svg)](https://travis-ci.org/csMACnz/BCLExtensions) @@ -12,11 +21,6 @@ BCLExtensions [![Coverage Status](https://img.shields.io/coveralls/csMACnz/BCLExtensions.svg)](https://coveralls.io/r/csMACnz/BCLExtensions?branch=master) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3770/badge.svg)](https://scan.coverity.com/projects/3770) -[![Stories in Ready](https://badge.waffle.io/csmacnz/BCLExtensions.png?label=ready&title=Ready)](https://waffle.io/csmacnz/BCLExtensions) -[![Stories in progress](https://badge.waffle.io/csmacnz/BCLExtensions.png?label=in%20progress&title=In%20Progress)](https://waffle.io/csmacnz/BCLExtensions) -[![Issue Stats](http://www.issuestats.com/github/csMACnz/BCLExtensions/badge/pr)](http://www.issuestats.com/github/csMACnz/BCLExtensions) -[![Issue Stats](http://www.issuestats.com/github/csMACnz/BCLExtensions/badge/issue)](http://www.issuestats.com/github/csMACnz/BCLExtensions) - Base Class Library Extensions for C# base class library classes, across .Net, Silverlight, WinRT. For now, this is build upon the most generic PCL possible, but may explore specific additional components if required. @@ -31,258 +35,12 @@ PCL Profile(Profile328) * Xamarin.Android * Xamarin.iOS -At some point this can include nuget packages. - - -Proposed Extensions -=================== - -String Extensions ------------------ -* string Left(this string value, int length) -* string Right(this string value, int length) -* string SafeLeft(this string value, int length) -* string SafeRight(this string value, int length) -* string SafeToString<T>(this T item) -* string SafeTrim(this string value) -* string SafeTrimStart(this string value) -* string SafeTrimEnd(this string value) -* string SafeTruncate(this string value) -* string ToLines(this string value) -* string ToNoBlankLines(this string value) -* string JoinWith(this string value, string delimiter) -* string JoinAsLines(this string value) -* long NumberOfLines(this string s); -* long NumberOfNonBlankLines(this string s); -* bool IsNumeric(this string value, bool trimWhitespace = true) - -Timespan Extensions -------------------- -* TimeSpan Years(this int value) -* TimeSpan Months(this int value) -* TimeSpan Weeks(this int value) -* TimeSpan Days(this int value) -* TimeSpan Hours(this int value) -* TimeSpan Minutes(this int value) -* TimeSpan Seconds(this int value) -* TimeSpan Milliseconds(this int value) - - -DateTime Extensions -------------------- -* DateTime Ago(this TimeSpan interval) -* DateTime Since(this TimeSpan interval, DateTime origin) - - -(Mutable)Collection Extensions -------------------- -* void AddRange<T>(this ICollection<T> collection, IEnumerable<T> itemsToAppend) -* ICollection<T> RemoveEach<T>(this ICollection<T> collection) -* ICollection<T> RemoveEach<T>(this ICollection<T> collection, Func<T, bool> whereExpression) -* ICollection<T> RemoveEach<T>(this ICollection<T> collection, Func<T, int, bool> whereExpression) -* ICollection<T> RemoveEachInReverse<T>(this ICollection<T> collection) -* ICollection<T> RemoveEachInReverse<T>(this ICollection<T> collection, Func<T, bool> whereExpression) -* ICollection<T> RemoveEachInReverse<T>(this ICollection<T> collection, Func<T, int, bool> whereExpression) -* ICollection<T> OrNullIfEmpty(this ICollection<T> collection) -* ICollection<T> OrEmptyIfNull(this ICollection<T> collection) - - -IList Extensions ----------------------- -* IList<T> RemoveEach<T>(this IList<T> items) -* IList<T> RemoveEach<T>(this IList<T> items, Func<T, bool> whereExpression) -* IList<T> RemoveEach<T>(this IList<T> items, Func<T, int, bool> whereExpression) -* IList<T> RemoveEachInReverse<T>(this IList<T> items) -* IList<T> RemoveEachInReverse<T>(this IList<T> items, Func<T, bool> whereExpression) -* IList<T> RemoveEachInReverse<T>(this IList<T> items, Func<T, int, bool> whereExpression) -* IList<T> RemoveEachByIndex<T>(this IList<T> items) -* IList<T> RemoveEachByIndex<T>(this IList<T> items, Func<T, bool> whereExpression) -* IList<T> RemoveEachByIndex<T>(this IList<T> items, Func<T, int, bool> whereExpression) -* IList<T> RemoveEachByIndexInReverse<T>(this IList<T> items) -* IList<T> RemoveEachByIndexInReverse<T>(this IList<T> items, Func<T, bool> whereExpression) -* IList<T> RemoveEachByIndexInReverse<T>(this IList<T> items, Func<T, int, bool> whereExpression) -* IList<T> OrNullIfEmpty(this IList<T> items) -* IList<T> OrEmptyIfNull(this IList<T> items) - - -List Extensions ----------------------- -* List<T> RemoveEach<T>(this List<T> items) -* List<T> RemoveEach<T>(this List<T> items, Func<T, bool> whereExpression) -* List<T> RemoveEach<T>(this List<T> items, Func<T, int, bool> whereExpression) -* List<T> RemoveEachInReverse<T>(this List<T> items) -* List<T> RemoveEachInReverse<T>(this List<T> items, Func<T, bool> whereExpression) -* List<T> RemoveEachInReverse<T>(this List<T> items, Func<T, int, bool> whereExpression) -* List<T> RemoveEachByIndex<T>(this List<T> items) -* List<T> RemoveEachByIndex<T>(this List<T> items, Func<T, bool> whereExpression) -* List<T> RemoveEachByIndex<T>(this List<T> items, Func<T, int, bool> whereExpression) -* List<T> RemoveEachByIndexInReverse<T>(this List<T> items) -* List<T> RemoveEachByIndexInReverse<T>(this List<T> items, Func<T, bool> whereExpression) -* List<T> RemoveEachByIndexInReverse<T>(this List<T> items, Func<T, int, bool> whereExpression) -* List<T> OrNullIfEmpty(this List<T> items) -* List<T> OrEmptyIfNull(this List<T> items) - - -IEnumerable Extensions ----------------------- -* List<T> ToListOf<T>(this IEnumerable items) -* List<T> SafeToListOf<T>(this IEnumerable items) -* List<T> SafeToList<T>(this IEnumerable<T> items) -* T[] SafeToArray<T>(this IEnumerable<T> items) -* Dictionary<TKey, TItem> SafeToDictionary<TItem, TKey>(this IEnumerable<T> items, Func<TItem, TKey> keySelector) -* HashSet<T> SafeToHashSet<T>(this IEnumerable<T> items) -* HashSet<T> SafeToHashSet<T>(this IEnumerable<T> items, IEqualityComparer<T> equalityComparer) - - -Dictionary Extensions ---------------------- -* Dictionary<TKey, TValue> OrNullIfEmpty(this Dictionary<TKey, TValue> dictionary) -* Dictionary<TKey, TValue> OrEmptyIfNull(this Dictionary<TKey, TValue> dictionary) -* T GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key) where TValue : struct -* T GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue) - - -Type Extensions ---------------- -* bool DerivesFrom<Type>(this object item) where T : class -* bool IsNullable(this Type itemType) -* IEnumerable<Type> SafeGetTypes(this Assembly assembly) - - -EnumExtensions --------------- -* void EnsureIsEnum<T>() where T : struct, IComparable, IConvertible, IFormattable -* bool IsEnum<T>() where T : struct, IComparable, IConvertible, IFormattable -* void EnsureIsEnum(this object enumerationValue) -* bool IsEnum(this object enumerationValue) - - -IntExtensions -------------- -* bool IsBetween(this int value, int lowerLimit, int upperLimit) -* bool IsBetweenExclusive(this int value, int lowerLimit, int upperLimit) -* bool IsBetween(this int value, ExclusiveInteger lowerLimit, ExclusiveInteger upperLimit) -* bool IsBetween(this int value, InclusiveInteger lowerLimit, ExclusiveInteger upperLimit) -* bool IsBetween(this int value, ExclusiveInteger lowerLimit, InclusiveInteger upperLimit) -* bool IsBetween(this int value, InclusiveInteger lowerLimit, InclusiveInteger upperLimit) -* InclusiveInteger Inclusive(this int value) -* ExclusiveInteger Exclusive(this int value) - -Example : 5.IsBetween(2.Exclusive(), 5.Inclusive()) - - -LongExtensions -------------- -* bool IsBetween(this long value, long lowerLimit, long upperLimit) -* bool IsBetweenExclusive(this long value, long lowerLimit, long upperLimit) -* bool IsBetween(this long value, ExclusiveLongInteger lowerLimit, ExclusiveLongInteger upperLimit) -* bool IsBetween(this long value, InclusiveLongInteger lowerLimit, ExclusiveLongInteger upperLimit) -* bool IsBetween(this long value, ExclusiveLongInteger lowerLimit, InclusiveLongInteger upperLimit) -* bool IsBetween(this long value, InclusiveLongInteger lowerLimit, InclusiveLongInteger upperLimit) -* InclusiveLongInteger Inclusive(this long value) -* ExclusiveLongInteger Exclusive(this long value) - -Example: 5.IsBetween(2.Exclusive(), 5.Inclusive()) - - -DecimalExtensions -------------- -* bool IsBetween(this decimal value, decimal lowerLimit, decimal upperLimit) -* bool IsBetweenExclusive(this decimal value, decimal lowerLimit, decimal upperLimit) -* bool IsBetween(this decimal value, ExclusiveDecimal lowerLimit, ExclusiveDecimal upperLimit) -* bool IsBetween(this decimal value, InclusiveDecimal lowerLimit, ExclusiveDecimal upperLimit) -* bool IsBetween(this decimal value, ExclusiveDecimal lowerLimit, InclusiveDecimal upperLimit) -* bool IsBetween(this decimal value, InclusiveDecimal lowerLimit, InclusiveDecimal upperLimit) -* InclusiveDecimal Inclusive(this decimal value) -* ExclusiveDecimal Exclusive(this decimal value) - -Example: (5m).IsBetween((2m).Exclusive(), (5m).Inclusive()) - - -Func Extensions ----------------------- -* Action AsActionUsing<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> action, T1 parameter1, T2 parameter2, T3 parameter3) -* Action AsActionUsing<T1, T2, T3, T4, TResult>(this Func<T1, T2, T3, T4, TResult> action, T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4) -* Action AsActionUsing<T1, T2, T3, T4, T5, TResult>(this Func<T1, T2, T3, T4, T5, TResult> action, T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4, T5 parameter5) -* Action AsActionUsing<T1, T2, T3, T4, T5, T6, TResult>(this Func<T1, T2, T3, T4, T5, T6, TResult> action, T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4, T5 parameter5, T6 parameter6) -* Action AsActionUsing<T1, T2, T3, T4, T5, T6, T7, TResult>(this Func<T1, T2, T3, T4, T5, T6, T7, TResult> action, T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4, T5 parameter5, T6 parameter6, T7 parameter7) -* Action AsActionUsing<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(this Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> action, T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4, T5 parameter5, T6 parameter6, T7 parameter7, T8 parameter8) - - -Action Extensions ----------------------- -* Action AsActionUsing<T1>(this Action<T1> action, T1 parameter1) -* Action AsActionUsing<T1, T2>(this Action<T1, T2> action, T1 parameter1, T2 parameter2) -* Action AsActionUsing<T1, T2, T3>(this Action<T1, T2, T3> action, T1 parameter1, T2 parameter2, T3 parameter3) -* Action AsActionUsing<T1, T2, T3, T4>(this Action<T1, T2, T3, T4> action, T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4) -* Action AsActionUsing<T1, T2, T3, T4, T5>(this Action<T1, T2, T3, T4, T5> action, T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4, T5 parameter5) -* Action AsActionUsing<T1, T2, T3, T4, T5, T6>(this Action<T1, T2, T3, T4, T5, T6> action, T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4, T5 parameter5, T6 parameter6) -* Action AsActionUsing<T1, T2, T3, T4, T5, T6, T7>(this Action<T1, T2, T3, T4, T5, T6, T7> action, T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4, T5 parameter5, T6 parameter6, T7 parameter7) -* Action AsActionUsing<T1, T2, T3, T4, T5, T6, T7, T8>(this Action<T1, T2, T3, T4, T5, T6, T7, T8> action, T1 parameter1, T2 parameter2, T3 parameter3, T4 parameter4, T5 parameter5, T6 parameter6, T7 parameter7, T8 parameter8) - - -ExpressionExtensions --------------------- -* string GetMemberName<TExpressionBody>(this Expression<TExpressionBody> expression) - - -Example: ExpressionExtensions.GetMemberName(() => MyProperty) - - -Other +Nuget ----- -* Build implementation of ContractAnnotation - -Completed Extensions -==================== - -Object Extensions ------------------ -* void EnsureIsNotNull(this object instance) -* void EnsureIsNotNull(this object instance, string argumentName) -* bool IsNotNull(this object instance) -* bool IsNull(this object instance) - - -Generic Extensions ------------------ -* T GetValueOrDefault<T>(this T item, T defaultValue) where T : class - - -IEnumerable Extensions ----------------------- -* bool IsNotEmpty<TItem>(this IEnumerable<TItem> items) -* bool IsNullOrEmpty<TItem>(this IEnumerable<TItem> items) -* IEnumerable<TItem> OrEmptyIfNull<TItem>(this IEnumerable<TItem> items) -* IEnumerable<TItem> OrNullIfEmpty<TItem>(this IEnumerable<TItem> items) - - -String Extensions ------------------ -* string FormatWith(this string format, params object[] parameters) -* bool IsNotNullOrWhitespace(this String s) -* bool IsNullOrWhitespace(this String s) -* string ValueOrEmptyIfNull(this string value) -* string ValueOrEmptyIfNullOrWhitespace(this string value) -* string ValueOrIfNull(this string value, String replacement) -* string ValueOrIfNullOrWhitespace(this string value, String replacement) -* string ValueOrNullIfWhitespace(this string value) - - -Type Extensions ---------------- -* bool IsOfType<T>(this object item) - -Array Extensions ----------------------- -* void Clear<T>(this T[] items) -* T[] OrNullIfEmpty<T>(this T[] items) -* T[] OrEmptyIfNull<T>(this T[] items) +You can install the nuget package using `Install-Package BCLExtensions` or by heading to the [Nuget Package Page](https://www.nuget.org/packages/BCLExtensions). +Extensions +---------- -Func Extensions ----------------------- -* Action AsAction<T>(this Func<T> function) -* Action AsActionUsing<TOutput, TParameter>(this Func<TParameter, TOutput> function, TParameter parameter) -* Action AsActionUsing<TOutput, TParameter1, TParameter2>(this Func<TParameter1, TParameter2, TOutput> function, TParameter1 parameter1, TParameter2 parameter2) +You can view the list if extensions available and future extensions to come on the [Extensions Wiki Page](https://github.com/csMACnz/BCLExtensions/wiki/Extensions). diff --git a/build.tasks.ps1 b/build.tasks.ps1 index d40cab5..c1d5e2c 100644 --- a/build.tasks.ps1 +++ b/build.tasks.ps1 @@ -86,59 +86,25 @@ task build { exec { msbuild "/t:Clean;Build" "/p:Configuration=$configuration" $sln_file } } -task appveyor-checkCoverity { - if($env:APPVEYOR_SCHEDULED_BUILD -eq "True") { - #download coverity - Invoke-WebRequest -Uri "https://scan.coverity.com/download/cxx/win_64" -Body @{ project = "$env:APPVEYOR_REPO_NAME"; token = "$env:COVERITY_TOKEN" } -OutFile "$env:APPVEYOR_BUILD_FOLDER\coverity.zip" - - Expand-Archive .\coverity.zip - - $script:runCoverity = $true - $script:covbuild = (Resolve-Path ".\cov-analysis-win64-*\bin\cov-build.exe").ToString() - } -} - task setup-coverity-local { - $script:runCoverity = $true - $script:covbuild = "cov-build" $env:APPVEYOR_BUILD_FOLDER = "." $env:APPVEYOR_BUILD_VERSION = $script:version $env:APPVEYOR_REPO_NAME = "csmacnz/BCLExtensions" - "You should have set the COVERITY_TOKEN environment variable already" + "You should have set the COVERITY_TOKEN and COVERITY_EMAILenvironment variable already" + $env:APPVEYOR_SCHEDULED_BUILD = "True" } task test-coverity -depends setup-coverity-local, coverity -task coverity -precondition { return $script:runCoverity }{ - & $script:covbuild --dir cov-int msbuild "/t:Clean;Build" "/p:Configuration=$configuration" $sln_file +task coverity -precondition { return $env:APPVEYOR_SCHEDULED_BUILD -eq "True" }{ $coverityFileName = "BCLExtensions.coverity.$script:nugetVersion.zip" - Write-Zip -Path "cov-int" -OutputPath $coverityFileName + $PublishCoverity = (Resolve-Path ".\src\packages\PublishCoverity.*\PublishCoverity.exe").ToString() + + & cov-build --dir cov-int msbuild "/t:Clean;Build" "/p:Configuration=$configuration" $sln_file + + & $PublishCoverity compress -o $coverityFileName - #TODO an app for this: - Add-Type -AssemblyName "System.Net.Http" - $client = New-Object Net.Http.HttpClient - $client.Timeout = [TimeSpan]::FromMinutes(20) - $form = New-Object Net.Http.MultipartFormDataContent - [Net.Http.HttpContent]$formField = New-Object Net.Http.StringContent($env:COVERITY_TOKEN) - $form.Add($formField, "token") - $formField = New-Object Net.Http.StringContent($env:COVERITY_EMAIL) - $form.Add($formField, "email") - $fs = New-Object IO.FileStream("$env:APPVEYOR_BUILD_FOLDER\$coverityFileName", [IO.FileMode]::Open, [IO.FileAccess]::Read) - $formField = New-Object Net.Http.StreamContent($fs) - $form.Add($formField, "file", "$coverityFileName") - $formField = New-Object Net.Http.StringContent($script:nugetVersion) - $form.Add($formField, "version") - $formField = New-Object Net.Http.StringContent("AppVeyor scheduled build ($env:APPVEYOR_BUILD_VERSION).") - $form.Add($formField, "description") - $url = "https://scan.coverity.com/builds?project=$env:APPVEYOR_REPO_NAME" - $task = $client.PostAsync($url, $form) - try { - $task.Wait() # throws AggregateException on time-out - } catch [AggregateException] { - throw $_.Exception.InnerException - } - $task.Result - $fs.Close() + & $PublishCoverity publish -t $env:COVERITY_TOKEN -e $env:COVERITY_EMAIL -z $coverityFileName -d "AppVeyor scheduled build ($env:APPVEYOR_BUILD_VERSION)." --codeVersion $script:nugetVersion } task coverage -depends LocalTestSettings, build, coverage-only @@ -190,4 +156,4 @@ task appveyor-install -depends GitVersion, RestoreNuGetPackages task appveyor-build -depends build -task appveyor-test -depends AppVeyorEnvironmentSettings, postbuild, appveyor-checkCoverity, coverity +task appveyor-test -depends AppVeyorEnvironmentSettings, postbuild, coverity diff --git a/package.json b/package.json deleted file mode 100644 index 89879c2..0000000 --- a/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "BCLExtensions", - "version": "0.1.0", - "description": "Base Class Library Extensions for C# base class library classes", - "repository": { - "type": "git", - "url": "https://github.com/csmacnz/BCLExtensions.git" - }, - "author": "csmacnz", - "bugs": { - "url": "https://github.com/csmacnz/BCLExtensions/issues" - }, - "homepage": "https://github.com/csmacnz/BCLExtensions", - "dependencies": { - "gulp": "^3.8.10", - "gulp-dotnet-assembly-info": "^0.1.10", - "gulp-msbuild": "^0.2.4", - "mstest": "^0.2.0" - } -} diff --git a/src/.nuget/packages.config b/src/.nuget/packages.config index 0e14aa1..53d3bca 100644 --- a/src/.nuget/packages.config +++ b/src/.nuget/packages.config @@ -1,6 +1,7 @@  - + + diff --git a/src/BCLExtensions.Tests/ActionExtensions/AsActionUsingTests.cs b/src/BCLExtensions.Tests/ActionExtensions/AsActionUsingTests.cs new file mode 100644 index 0000000..bfc006b --- /dev/null +++ b/src/BCLExtensions.Tests/ActionExtensions/AsActionUsingTests.cs @@ -0,0 +1,61 @@ +using System; +using Xunit; + +namespace BCLExtensions.Tests.ActionExtensions +{ + + public class AsActionUsingTests + { + [Fact] + public void SampleActionIsValid() + { + Assert.DoesNotThrow(() => SampleAction(42)); + } + + [Fact] + public void ResultNotNull() + { + Action function = SampleAction; + + var action = function.AsActionUsing(12); + + Assert.NotNull(action); + } + + private void SampleAction(int parameter) + { + + } + + [Fact] + public void InternalFunctionExecutes() + { + bool internalFunctionWasCalled = false; + Action action = parameter => + { + internalFunctionWasCalled = true; + }; + var result = action.AsActionUsing(12); + result(); + + Assert.True(internalFunctionWasCalled); + } + + + [Fact] + public void InternalFunctionCapturesCorrectParameter() + { + const int expectedParameter = 12; + int passedParameter = 0; + Action action = parameter => + { + passedParameter = parameter; + }; + + var result = action.AsActionUsing(expectedParameter); + result(); + + Assert.Equal(expectedParameter, passedParameter); + } + } +} diff --git a/src/BCLExtensions.Tests/ActionExtensions/AsActionUsingWithThreeParametersTests.cs b/src/BCLExtensions.Tests/ActionExtensions/AsActionUsingWithThreeParametersTests.cs new file mode 100644 index 0000000..54ca2b9 --- /dev/null +++ b/src/BCLExtensions.Tests/ActionExtensions/AsActionUsingWithThreeParametersTests.cs @@ -0,0 +1,69 @@ +using System; +using Xunit; + +namespace BCLExtensions.Tests.ActionExtensions +{ + + public class AsActionUsingWithThreeParametersTests + { + [Fact] + public void SampleActionIsValid() + { + Assert.DoesNotThrow(() => SampleAction(42, "Test", true)); + } + + [Fact] + public void ResultNotNull() + { + Action action = SampleAction; + + var result = action.AsActionUsing(12, "12", false); + + Assert.NotNull(result); + } + + [Fact] + public void InternalActionExecutes() + { + bool internalActionWasCalled = false; + Action action = (p1,p2,p3) => + { + internalActionWasCalled = true; + }; + var result = action.AsActionUsing(12,"24", false); + result(); + + Assert.True(internalActionWasCalled); + } + + + [Fact] + public void InternalActionCapturesCorrectParameters() + { + const int expectedParameter1 = 12; + const string expectedParameter2 = "24"; + const bool expectedParameter3 = true; + int passedParameter1 = 0; + string passedParameter2 = null; + bool passedParameter3 = false; + Action action = (p1,p2,p3) => + { + passedParameter1 = p1; + passedParameter2 = p2; + passedParameter3 = p3; + }; + + var result = action.AsActionUsing(expectedParameter1, expectedParameter2, expectedParameter3); + result(); + + Assert.Equal(expectedParameter1, passedParameter1); + Assert.Equal(expectedParameter2, passedParameter2); + Assert.Equal(expectedParameter3, passedParameter3); + } + + private void SampleAction(int parameter1, string parameter2, bool parameter3) + { + } + + } +} diff --git a/src/BCLExtensions.Tests/ActionExtensions/AsActionUsingWithTwoParametersTests.cs b/src/BCLExtensions.Tests/ActionExtensions/AsActionUsingWithTwoParametersTests.cs new file mode 100644 index 0000000..684d27f --- /dev/null +++ b/src/BCLExtensions.Tests/ActionExtensions/AsActionUsingWithTwoParametersTests.cs @@ -0,0 +1,65 @@ +using System; +using Xunit; + +namespace BCLExtensions.Tests.ActionExtensions +{ + + public class AsActionUsingWithTwoParametersTests + { + [Fact] + public void SampleActionIsValid() + { + Assert.DoesNotThrow(() => SampleAction(42, "Test")); + } + + [Fact] + public void ResultNotNull() + { + Action action = SampleAction; + + var result = action.AsActionUsing(12, "12"); + + Assert.NotNull(result); + } + + [Fact] + public void InternalActionExecutes() + { + bool internalActionWasCalled = false; + Action action = (p1,p2) => + { + internalActionWasCalled = true; + }; + var result = action.AsActionUsing(12,"24"); + result(); + + Assert.True(internalActionWasCalled); + } + + + [Fact] + public void InternalActionCapturesCorrectParameters() + { + const int expectedParameter1 = 12; + const string expectedParameter2 = "24"; + int passedParameter1 = 0; + string passedParameter2 = null; + Action action = (p1,p2) => + { + passedParameter1 = p1; + passedParameter2 = p2; + }; + + var result = action.AsActionUsing(expectedParameter1, expectedParameter2); + result(); + + Assert.Equal(expectedParameter1, passedParameter1); + Assert.Equal(expectedParameter2, passedParameter2); + } + + private void SampleAction(int parameter1, string parameter2) + { + } + + } +} diff --git a/src/BCLExtensions.Tests/BCLExtensions.Tests.csproj b/src/BCLExtensions.Tests/BCLExtensions.Tests.csproj index 0dac99d..b08c289 100644 --- a/src/BCLExtensions.Tests/BCLExtensions.Tests.csproj +++ b/src/BCLExtensions.Tests/BCLExtensions.Tests.csproj @@ -59,13 +59,37 @@ + + + - + + + + + + + + + + + + + + + + + + + + + Code + @@ -93,7 +117,6 @@ - diff --git a/src/BCLExtensions.Tests/FuncExtensions/AsActionUsingWithThreeParametersTests.cs b/src/BCLExtensions.Tests/FuncExtensions/AsActionUsingWithThreeParametersTests.cs new file mode 100644 index 0000000..1ae3e98 --- /dev/null +++ b/src/BCLExtensions.Tests/FuncExtensions/AsActionUsingWithThreeParametersTests.cs @@ -0,0 +1,72 @@ +using System; +using Xunit; + +namespace BCLExtensions.Tests.FuncExtensions +{ + + public class AsActionUsingWithThreeParametersTests + { + [Fact] + public void SampleFunctionIsValid() + { + Assert.DoesNotThrow(() => SampleFunction(42, "Test", true)); + } + + [Fact] + public void ResultNotNull() + { + Func function = SampleFunction; + + var action = function.AsActionUsing(12, "12", false); + + Assert.NotNull(action); + } + + [Fact] + public void InternalFunctionExecutes() + { + bool internalFunctionWasCalled = false; + Func function = (p1,p2,p3) => + { + internalFunctionWasCalled = true; + return 42m; + }; + var action = function.AsActionUsing(12,"24",true); + action(); + + Assert.True(internalFunctionWasCalled); + } + + + [Fact] + public void InternalFunctionCapturesCorrectParameters() + { + const int expectedParameter1 = 12; + const string expectedParameter2 = "24"; + const bool expectedParameter3 = true; + int passedParameter1 = 0; + string passedParameter2 = null; + bool passedParameter3 = false; + Func function = (p1,p2,p3) => + { + passedParameter1 = p1; + passedParameter2 = p2; + passedParameter3 = p3; + return 42; + }; + + var action = function.AsActionUsing(expectedParameter1, expectedParameter2, expectedParameter3); + action(); + + Assert.Equal(expectedParameter1, passedParameter1); + Assert.Equal(expectedParameter2, passedParameter2); + Assert.Equal(expectedParameter3, passedParameter3); + } + + private decimal SampleFunction(int parameter1, string parameter2, bool parameter3) + { + return 42m; + } + + } +} diff --git a/src/BCLExtensions.Tests/FuncExtensions/AsActionUsingTests - Copy.cs b/src/BCLExtensions.Tests/FuncExtensions/AsActionUsingWithTwoParametersTests.cs similarity index 100% rename from src/BCLExtensions.Tests/FuncExtensions/AsActionUsingTests - Copy.cs rename to src/BCLExtensions.Tests/FuncExtensions/AsActionUsingWithTwoParametersTests.cs diff --git a/src/BCLExtensions.Tests/IntExtensions/EnsureOrderTests.cs b/src/BCLExtensions.Tests/IntExtensions/EnsureOrderTests.cs new file mode 100644 index 0000000..6ab48da --- /dev/null +++ b/src/BCLExtensions.Tests/IntExtensions/EnsureOrderTests.cs @@ -0,0 +1,44 @@ +using System; +using BCLExtensions.Tests.TestHelpers; +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.IntExtensions +{ + public class EnsureOrderTests + { + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(1, 0)] + [InlineData(2, 1)] + [InlineData(3, 2)] + [InlineData(0, -1)] + [InlineData(-1, -2)] + [InlineData(-2, -3)] + [InlineData(42, -42)] + public void InvalidOrderThrowsExceptions(int first, int second) + { + Action ensureOrder = BCLExtensions.IntExtensions.EnsureOrder; + + Assert.Throws(ensureOrder.AsActionUsing(first, second).AsThrowsDelegate()); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(int.MinValue, int.MaxValue)] + [InlineData(0, 1)] + [InlineData(1, 2)] + [InlineData(2, 3)] + [InlineData(-1, 0)] + [InlineData(-2, -1)] + [InlineData(-3, -2)] + [InlineData(42, 42)] + [InlineData(-42, 42)] + public void ValidDataDoesNotThrowExceptions(int first, int second) + { + Action ensureOrder = BCLExtensions.IntExtensions.EnsureOrder; + + Assert.DoesNotThrow(ensureOrder.AsActionUsing(first, second).AsThrowsDelegate()); + } + } +} diff --git a/src/BCLExtensions.Tests/IntExtensions/IsBetweenExclusiveExclusiveTests.cs b/src/BCLExtensions.Tests/IntExtensions/IsBetweenExclusiveExclusiveTests.cs new file mode 100644 index 0000000..b34741b --- /dev/null +++ b/src/BCLExtensions.Tests/IntExtensions/IsBetweenExclusiveExclusiveTests.cs @@ -0,0 +1,48 @@ +using System; +using BCLExtensions.Tests.TestHelpers; +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.IntExtensions +{ + public class IsBetweenExclusiveExclusiveTests + { + [Theory] + [InlineData(0, -1, 1)] + [InlineData(0, int.MinValue, int.MaxValue)] + [InlineData(42, 30, 60)] + [InlineData(-30, -40, -20)] + public void InputToIsBetweenWithLimitsReturnsTrue(int input, int lowerLimit, int upperLimit) + { + var result = input.IsBetween(lowerLimit.Exclusive(), upperLimit.Exclusive()); + + Assert.True(result); + } + + [Theory] + [InlineData(0, 0, 0)] + [InlineData(42, 42, 42)] + [InlineData(5, 5, 6)] + [InlineData(6, 5, 6)] + [InlineData(0, 1, 2)] + [InlineData(0, -2, -1)] + [InlineData(42, 5, 12)] + [InlineData(42, 50, 100)] + [InlineData(-30, -20, -10)] + [InlineData(-30, -50, -40)] + public void InputToIsBetweenWithLimitsReturnsFalse(int input, int lowerLimit, int upperLimit) + { + var result = input.IsBetween(lowerLimit.Exclusive(), upperLimit.Exclusive()); + + Assert.False(result); + } + + [Fact] + public void LimitsAreReversedThrowsException() + { + Func isBetween = BCLExtensions.IntExtensions.IsBetween; + + Assert.Throws(isBetween.AsActionUsing(0, 100.Exclusive(), 20.Exclusive()).AsThrowsDelegate()); + } + } +} diff --git a/src/BCLExtensions.Tests/IntExtensions/IsBetweenExclusiveInclusiveTests.cs b/src/BCLExtensions.Tests/IntExtensions/IsBetweenExclusiveInclusiveTests.cs new file mode 100644 index 0000000..195ad08 --- /dev/null +++ b/src/BCLExtensions.Tests/IntExtensions/IsBetweenExclusiveInclusiveTests.cs @@ -0,0 +1,48 @@ +using System; +using BCLExtensions.Tests.TestHelpers; +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.IntExtensions +{ + public class IsBetweenExclusiveInclusiveTests + { + [Theory] + [InlineData(0, -1, 1)] + [InlineData(6, 5, 6)] + [InlineData(0, int.MinValue, int.MaxValue)] + [InlineData(42, 30, 60)] + [InlineData(-30, -40, -20)] + public void InputToIsBetweenWithLimitsReturnsTrue(int input, int lowerLimit, int upperLimit) + { + var result = input.IsBetween(lowerLimit.Exclusive(), upperLimit.Inclusive()); + + Assert.True(result); + } + + [Theory] + [InlineData(0, 0, 0)] + [InlineData(42, 42, 42)] + [InlineData(5, 5, 6)] + [InlineData(0, 1, 2)] + [InlineData(0, -2, -1)] + [InlineData(42, 5, 12)] + [InlineData(42, 50, 100)] + [InlineData(-30, -20, -10)] + [InlineData(-30, -50, -40)] + public void InputToIsBetweenWithLimitsReturnsFalse(int input, int lowerLimit, int upperLimit) + { + var result = input.IsBetween(lowerLimit.Exclusive(), upperLimit.Inclusive()); + + Assert.False(result); + } + + [Fact] + public void LimitsAreReversedThrowsException() + { + Func isBetween = BCLExtensions.IntExtensions.IsBetween; + + Assert.Throws(isBetween.AsActionUsing(0, 100.Exclusive(), 20.Inclusive()).AsThrowsDelegate()); + } + } +} diff --git a/src/BCLExtensions.Tests/IntExtensions/IsBetweenExclusiveTests.cs b/src/BCLExtensions.Tests/IntExtensions/IsBetweenExclusiveTests.cs new file mode 100644 index 0000000..843ac47 --- /dev/null +++ b/src/BCLExtensions.Tests/IntExtensions/IsBetweenExclusiveTests.cs @@ -0,0 +1,48 @@ +using System; +using BCLExtensions.Tests.TestHelpers; +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.IntExtensions +{ + public class IsBetweenExclusiveTests + { + [Theory] + [InlineData(0,-1,1)] + [InlineData(0,int.MinValue,int.MaxValue)] + [InlineData(42, 30, 60)] + [InlineData(-30, -40, -20)] + public void InputToIsBetweenWithLimitsReturnsTrue(int input, int lowerLimit, int upperLimit) + { + var result = input.IsBetweenExclusive(lowerLimit, upperLimit); + + Assert.True(result); + } + + [Theory] + [InlineData(0, 0, 0)] + [InlineData(42, 42, 42)] + [InlineData(5, 5, 6)] + [InlineData(6, 5, 6)] + [InlineData(0, 1, 2)] + [InlineData(0, -2, -1)] + [InlineData(42, 5, 12)] + [InlineData(42, 50, 100)] + [InlineData(-30, -20, -10)] + [InlineData(-30, -50, -40)] + public void InputToIsBetweenWithLimitsReturnsFalse(int input, int lowerLimit, int upperLimit) + { + var result = input.IsBetweenExclusive(lowerLimit, upperLimit); + + Assert.False(result); + } + + [Fact] + public void LimitsAreReversedThrowsException() + { + Func isBetween = BCLExtensions.IntExtensions.IsBetweenExclusive; + + Assert.Throws(isBetween.AsActionUsing(0, 100, 20).AsThrowsDelegate()); + } + } +} diff --git a/src/BCLExtensions.Tests/IntExtensions/IsBetweenInclusiveExclusiveTests.cs b/src/BCLExtensions.Tests/IntExtensions/IsBetweenInclusiveExclusiveTests.cs new file mode 100644 index 0000000..9514591 --- /dev/null +++ b/src/BCLExtensions.Tests/IntExtensions/IsBetweenInclusiveExclusiveTests.cs @@ -0,0 +1,48 @@ +using System; +using BCLExtensions.Tests.TestHelpers; +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.IntExtensions +{ + public class IsBetweenInclusiveExclusiveTests + { + [Theory] + [InlineData(0, -1, 1)] + [InlineData(5, 5, 6)] + [InlineData(0, int.MinValue, int.MaxValue)] + [InlineData(42, 30, 60)] + [InlineData(-30, -40, -20)] + public void InputToIsBetweenWithLimitsReturnsTrue(int input, int lowerLimit, int upperLimit) + { + var result = input.IsBetween(lowerLimit.Inclusive(), upperLimit.Exclusive()); + + Assert.True(result); + } + + [Theory] + [InlineData(0, 0, 0)] + [InlineData(42, 42, 42)] + [InlineData(6, 5, 6)] + [InlineData(0, 1, 2)] + [InlineData(0, -2, -1)] + [InlineData(42, 5, 12)] + [InlineData(42, 50, 100)] + [InlineData(-30, -20, -10)] + [InlineData(-30, -50, -40)] + public void InputToIsBetweenWithLimitsReturnsFalse(int input, int lowerLimit, int upperLimit) + { + var result = input.IsBetween(lowerLimit.Inclusive(), upperLimit.Exclusive()); + + Assert.False(result); + } + + [Fact] + public void LimitsAreReversedThrowsException() + { + Func isBetween = BCLExtensions.IntExtensions.IsBetween; + + Assert.Throws(isBetween.AsActionUsing(0, 100.Inclusive(), 20.Exclusive()).AsThrowsDelegate()); + } + } +} diff --git a/src/BCLExtensions.Tests/IntExtensions/IsBetweenInclusiveInclusiveTests.cs b/src/BCLExtensions.Tests/IntExtensions/IsBetweenInclusiveInclusiveTests.cs new file mode 100644 index 0000000..ab0e017 --- /dev/null +++ b/src/BCLExtensions.Tests/IntExtensions/IsBetweenInclusiveInclusiveTests.cs @@ -0,0 +1,48 @@ +using System; +using BCLExtensions.Tests.TestHelpers; +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.IntExtensions +{ + public class IsBetweenInclusiveInclusiveTests + { + [Theory] + [InlineData(0, 0, 0)] + [InlineData(42, 42, 42)] + [InlineData(5, 5, 6)] + [InlineData(6, 5, 6)] + [InlineData(0, -1, 1)] + [InlineData(0, int.MinValue, int.MaxValue)] + [InlineData(42, 30, 60)] + [InlineData(-30, -40, -20)] + public void InputToIsBetweenWithLimitsReturnsTrue(int input, int lowerLimit, int upperLimit) + { + var result = input.IsBetween(lowerLimit.Inclusive(), upperLimit.Inclusive()); + + Assert.True(result); + } + + [Theory] + [InlineData(0, 1, 2)] + [InlineData(0, -2, -1)] + [InlineData(42, 5, 12)] + [InlineData(42, 50, 100)] + [InlineData(-30, -20, -10)] + [InlineData(-30, -50, -40)] + public void InputToIsBetweenWithLimitsReturnsFalse(int input, int lowerLimit, int upperLimit) + { + var result = input.IsBetween(lowerLimit.Inclusive(), upperLimit.Inclusive()); + + Assert.False(result); + } + + [Fact] + public void LimitsAreReversedThrowsException() + { + Func isBetween = BCLExtensions.IntExtensions.IsBetween; + + Assert.Throws(isBetween.AsActionUsing(0, 100.Inclusive(), 20.Inclusive()).AsThrowsDelegate()); + } + } +} diff --git a/src/BCLExtensions.Tests/IntExtensions/IsBetweenTests.cs b/src/BCLExtensions.Tests/IntExtensions/IsBetweenTests.cs new file mode 100644 index 0000000..1dd8a79 --- /dev/null +++ b/src/BCLExtensions.Tests/IntExtensions/IsBetweenTests.cs @@ -0,0 +1,48 @@ +using System; +using BCLExtensions.Tests.TestHelpers; +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.IntExtensions +{ + public class IsBetweenTests + { + [Theory] + [InlineData(0, 0, 0)] + [InlineData(42, 42, 42)] + [InlineData(5, 5, 6)] + [InlineData(6, 5, 6)] + [InlineData(0,-1,1)] + [InlineData(0,int.MinValue,int.MaxValue)] + [InlineData(42, 30, 60)] + [InlineData(-30, -40, -20)] + public void InputToIsBetweenWithLimitsReturnsTrue(int input, int lowerLimit, int upperLimit) + { + var result = input.IsBetween(lowerLimit, upperLimit); + + Assert.True(result); + } + + [Theory] + [InlineData(0, 1, 2)] + [InlineData(0, -2, -1)] + [InlineData(42, 5, 12)] + [InlineData(42, 50, 100)] + [InlineData(-30, -20, -10)] + [InlineData(-30, -50, -40)] + public void InputToIsBetweenWithLimitsReturnsFalse(int input, int lowerLimit, int upperLimit) + { + var result = input.IsBetween(lowerLimit, upperLimit); + + Assert.False(result); + } + + [Fact] + public void LimitsAreReversedThrowsException() + { + Func isBetween = BCLExtensions.IntExtensions.IsBetween; + + Assert.Throws(isBetween.AsActionUsing(0, 100, 20).AsThrowsDelegate()); + } + } +} diff --git a/src/BCLExtensions.Tests/ObjectExtensions/EnsureIsNotNullTests.cs b/src/BCLExtensions.Tests/ObjectExtensions/EnsureIsNotNullTests.cs index d2956ac..cd3e16e 100644 --- a/src/BCLExtensions.Tests/ObjectExtensions/EnsureIsNotNullTests.cs +++ b/src/BCLExtensions.Tests/ObjectExtensions/EnsureIsNotNullTests.cs @@ -1,4 +1,5 @@ using System; +using BCLExtensions.Tests.TestHelpers; using Xunit; namespace BCLExtensions.Tests.ObjectExtensions @@ -11,7 +12,8 @@ public class EnsureIsNotNullTests public void WhenInstanceIsNullThrowsException() { object instance = null; - Assert.Throws(() => instance.EnsureIsNotNull()); + Action action = BCLExtensions.ObjectExtensions.EnsureIsNotNull; + Assert.Throws(action.AsActionUsing(instance).AsThrowsDelegate()); } [Fact] @@ -32,7 +34,8 @@ public void WhenInstanceIsNotNullWithNamedArgumentThenRunsSuccessfully() public void WhenInstanceIsNullWithNamedArgumentThrowsException() { object instance = null; - Assert.Throws(() => instance.EnsureIsNotNull(instanceArgumentName)); + Action action = BCLExtensions.ObjectExtensions.EnsureIsNotNull; + Assert.Throws(action.AsActionUsing(instance,instanceArgumentName).AsThrowsDelegate()); } [Fact] @@ -40,7 +43,8 @@ public void WhenInstanceIsNullWithNamedArgumentCorrectArgumentNameIsProvidedInEx { object instance = null; - var exception = Assert.Throws(() => instance.EnsureIsNotNull(instanceArgumentName)); + Action action = BCLExtensions.ObjectExtensions.EnsureIsNotNull; + var exception = Assert.Throws(action.AsActionUsing(instance, instanceArgumentName).AsThrowsDelegate()); Assert.Equal(instanceArgumentName, exception.ParamName); } diff --git a/src/BCLExtensions.Tests/StringExtensions/LeftTests.cs b/src/BCLExtensions.Tests/StringExtensions/LeftTests.cs new file mode 100644 index 0000000..8034107 --- /dev/null +++ b/src/BCLExtensions.Tests/StringExtensions/LeftTests.cs @@ -0,0 +1,36 @@ +using System; +using BCLExtensions.Tests.TestHelpers; +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.StringExtensions +{ + public class LeftTests + { + [Theory] + [InlineData("Hello World", 5, "Hello")] + [InlineData("Not Long Enough", 100, "Not Long Enough")] + [InlineData("", 0, "")] + [InlineData("", 5, "")] + [InlineData("Becomes Empty String", 0, "")] + public void InputReturnsExpectedOutput(string input, int length, string expected) + { + var formattedString = input.Left(length); + Assert.Equal(expected, formattedString); + } + + [Fact] + public void NullInputThrowsException() + { + Func left = BCLExtensions.StringExtensions.Left; + Assert.Throws(left.AsActionUsing(null, 0).AsThrowsDelegate()); + } + + [Fact] + public void NegativeLengthThrowsException() + { + Func left = BCLExtensions.StringExtensions.Left; + Assert.Throws(left.AsActionUsing("Hello World", -1).AsThrowsDelegate()); + } + } +} diff --git a/src/BCLExtensions.Tests/StringExtensions/RightTests.cs b/src/BCLExtensions.Tests/StringExtensions/RightTests.cs new file mode 100644 index 0000000..cec6ea5 --- /dev/null +++ b/src/BCLExtensions.Tests/StringExtensions/RightTests.cs @@ -0,0 +1,36 @@ +using System; +using BCLExtensions.Tests.TestHelpers; +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.StringExtensions +{ + public class RightTests + { + [Theory] + [InlineData("Hello World", 5, "World")] + [InlineData("Not Long Enough", 100, "Not Long Enough")] + [InlineData("", 0, "")] + [InlineData("", 5, "")] + [InlineData("Becomes Empty String", 0, "")] + public void InputReturnsExpectedOutput(string input, int length, string expected) + { + var formattedString = input.Right(length); + Assert.Equal(expected, formattedString); + } + + [Fact] + public void NullInputThrowsException() + { + Func right = BCLExtensions.StringExtensions.Right; + Assert.Throws(right.AsActionUsing(null, 0).AsThrowsDelegate()); + } + + [Fact] + public void NegativeLengthThrowsException() + { + Func right = BCLExtensions.StringExtensions.Right; + Assert.Throws(right.AsActionUsing("Hello World", -1).AsThrowsDelegate()); + } + } +} diff --git a/src/BCLExtensions.Tests/StringExtensions/SafeLeftTests.cs b/src/BCLExtensions.Tests/StringExtensions/SafeLeftTests.cs new file mode 100644 index 0000000..e549761 --- /dev/null +++ b/src/BCLExtensions.Tests/StringExtensions/SafeLeftTests.cs @@ -0,0 +1,50 @@ +using System; +using BCLExtensions.Tests.TestHelpers; +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.StringExtensions +{ + public class SafeLeftTests + { + [Theory] + [InlineData("Hello World", 5, "Hello")] + [InlineData("Not Long Enough", 100, "Not Long Enough")] + [InlineData("", 0, "")] + [InlineData("", 5, "")] + [InlineData("Becomes Empty String", 0, "")] + public void InputReturnsExpectedOutput(string input, int length, string expected) + { + var formattedString = input.SafeLeft(length); + Assert.Equal(expected, formattedString); + } + + [Theory] + [InlineData(0)] + [InlineData(5)] + [InlineData(int.MaxValue)] + public void NullInputReturnsEmptyString(int length) + { + string input = null; + + var formattedString = input.SafeLeft(length); + + Assert.Equal(string.Empty, formattedString); + } + + [Fact] + public void NegativeLengthThrowsException() + { + Func safeLeft = BCLExtensions.StringExtensions.SafeLeft; + Assert.Throws(safeLeft.AsActionUsing("Hello World", -1).AsThrowsDelegate()); + } + + + [Fact] + public void NegativeLengthOnNullThrowsException() + { + Func safeLeft = BCLExtensions.StringExtensions.SafeLeft; + Assert.Throws(safeLeft.AsActionUsing(null, -1).AsThrowsDelegate()); + } + } +} diff --git a/src/BCLExtensions.Tests/StringExtensions/SafeRightTests.cs b/src/BCLExtensions.Tests/StringExtensions/SafeRightTests.cs new file mode 100644 index 0000000..9ff3a3c --- /dev/null +++ b/src/BCLExtensions.Tests/StringExtensions/SafeRightTests.cs @@ -0,0 +1,51 @@ +using System; +using BCLExtensions.Tests.TestHelpers; +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.StringExtensions +{ + public class SafeRightTests + { + [Theory] + [InlineData("Hello World", 5, "World")] + [InlineData("Not Long Enough", 100, "Not Long Enough")] + [InlineData("", 0, "")] + [InlineData("", 5, "")] + [InlineData("Becomes Empty String", 0, "")] + public void InputReturnsExpectedOutput(string input, int length, string expected) + { + var formattedString = input.SafeRight(length); + Assert.Equal(expected, formattedString); + } + + [Theory] + [InlineData(0)] + [InlineData(5)] + [InlineData(int.MaxValue)] + public void NullInputReturnsEmptyString(int length) + { + string input = null; + + // ReSharper disable once ExpressionIsAlwaysNull + var formattedString = input.SafeRight(length); + + Assert.Equal(string.Empty, formattedString); + } + + [Fact] + public void NegativeLengthThrowsException() + { + Func safeRight = BCLExtensions.StringExtensions.SafeRight; + Assert.Throws(safeRight.AsActionUsing("Hello World", -1).AsThrowsDelegate()); + } + + + [Fact] + public void NegativeLengthOnNullThrowsException() + { + Func safeRight = BCLExtensions.StringExtensions.SafeRight; + Assert.Throws(safeRight.AsActionUsing(null, -1).AsThrowsDelegate()); + } + } +} diff --git a/src/BCLExtensions.Tests/StringExtensions/SafeToStringTests.cs b/src/BCLExtensions.Tests/StringExtensions/SafeToStringTests.cs new file mode 100644 index 0000000..e614bc0 --- /dev/null +++ b/src/BCLExtensions.Tests/StringExtensions/SafeToStringTests.cs @@ -0,0 +1,59 @@ +using Xunit; + +namespace BCLExtensions.Tests.StringExtensions +{ + public class SafeToStringTests + { + [Fact] + public void NullReturnsEmptyString() + { + object value = null; + + // ReSharper disable once ExpressionIsAlwaysNull + var result = value.SafeToString(); + + Assert.Equal(string.Empty, result); + } + + [Fact] + public void StringReturnsOriginalString() + { + const string expected = "String Object"; + + var result = expected.SafeToString(); + + Assert.Equal(expected, result); + } + + [Fact] + public void StringAsObjectReturnsOriginalString() + { + const string expected = "Test String"; + object value = expected; + + var result = value.SafeToString(); + + Assert.Equal(expected, result); + } + + [Fact] + public void CustomObjectReturnsCorrectString() + { + var value = new TestObject(); + + var result = value.SafeToString(); + + Assert.Equal(TestObject.ExpectedString, result); + } + + private class TestObject + { + public const string ExpectedString = "Sample String"; + + public override string ToString() + { + return ExpectedString; + } + } + } +} diff --git a/src/BCLExtensions.Tests/StringExtensions/SafeToStringWithNullStringTests.cs b/src/BCLExtensions.Tests/StringExtensions/SafeToStringWithNullStringTests.cs new file mode 100644 index 0000000..e441225 --- /dev/null +++ b/src/BCLExtensions.Tests/StringExtensions/SafeToStringWithNullStringTests.cs @@ -0,0 +1,82 @@ +using System; +using BCLExtensions.Tests.TestHelpers; +using Xunit; + +namespace BCLExtensions.Tests.StringExtensions +{ + public class SafeToStringWithNullStringTests + { + [Fact] + public void NullWithNullNullStringThrowsException() + { + Func safeToString = BCLExtensions.StringExtensions.SafeToString; + Assert.Throws(safeToString.AsActionUsing(null, null).AsThrowsDelegate()); + } + + [Fact] + public void NullReturnsEmptyString() + { + object value = null; + + // ReSharper disable once ExpressionIsAlwaysNull + var result = value.SafeToString("[NULL]"); + + Assert.Equal("[NULL]", result); + } + + [Fact] + public void StringWithNullNullStringThrowsException() + { + Func safeToString = BCLExtensions.StringExtensions.SafeToString; + Assert.Throws(safeToString.AsActionUsing("String Object", null).AsThrowsDelegate()); + } + + [Fact] + public void StringReturnsOriginalString() + { + const string expected = "String Object"; + + var result = expected.SafeToString("[NULL]"); + + Assert.Equal(expected, result); + } + + [Fact] + public void StringAsObjectReturnsOriginalString() + { + const string expected = "Test String"; + object value = expected; + + var result = value.SafeToString("[NULL]"); + + Assert.Equal(expected, result); + } + + [Fact] + public void CustomObjectReturnsCorrectString() + { + var value = new TestObject(); + + var result = value.SafeToString("[NULL]"); + + Assert.Equal(TestObject.ExpectedString, result); + } + + [Fact] + public void CustomObjectWithNullNullStringThrowsException() + { + Func safeToString = BCLExtensions.StringExtensions.SafeToString; + Assert.Throws(safeToString.AsActionUsing(new TestObject(), null).AsThrowsDelegate()); + } + + private class TestObject + { + public const string ExpectedString = "Sample String"; + + public override string ToString() + { + return ExpectedString; + } + } + } +} diff --git a/src/BCLExtensions.Tests/StringExtensions/SafeTrimEndTests.cs b/src/BCLExtensions.Tests/StringExtensions/SafeTrimEndTests.cs new file mode 100644 index 0000000..39a578e --- /dev/null +++ b/src/BCLExtensions.Tests/StringExtensions/SafeTrimEndTests.cs @@ -0,0 +1,34 @@ +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.StringExtensions +{ + public class SafeTrimEndTests + { + [Theory] + [InlineData("", "")] + [InlineData("Hello World", "Hello World")] + [InlineData("\nHello World\n", "\nHello World")] + [InlineData("\tHello World\t", "\tHello World")] + [InlineData(" Hello World ", " Hello World")] + [InlineData("Hello ", "Hello")] + [InlineData(" World", " World")] + [InlineData("Hello World", "Hello World")] + public void InputReturnsExpectedOutput(string input, string expected) + { + var result = input.SafeTrimEnd(); + + Assert.Equal(expected, result); + } + + [Fact] + public void NullInputReturnsEmptyString() + { + string input = null; + + var result = input.SafeTrimEnd(); + + Assert.Equal(string.Empty, result); + } + } +} diff --git a/src/BCLExtensions.Tests/StringExtensions/SafeTrimStartTests.cs b/src/BCLExtensions.Tests/StringExtensions/SafeTrimStartTests.cs new file mode 100644 index 0000000..8a9c829 --- /dev/null +++ b/src/BCLExtensions.Tests/StringExtensions/SafeTrimStartTests.cs @@ -0,0 +1,34 @@ +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.StringExtensions +{ + public class SafeTrimStartTests + { + [Theory] + [InlineData("", "")] + [InlineData("Hello World", "Hello World")] + [InlineData("\nHello World\n", "Hello World\n")] + [InlineData("\tHello World\t", "Hello World\t")] + [InlineData(" Hello World ", "Hello World ")] + [InlineData("Hello ", "Hello ")] + [InlineData(" World", "World")] + [InlineData("Hello World", "Hello World")] + public void InputReturnsExpectedOutput(string input, string expected) + { + var result = input.SafeTrimStart(); + + Assert.Equal(expected, result); + } + + [Fact] + public void NullInputReturnsEmptyString() + { + string input = null; + + var result = input.SafeTrimStart(); + + Assert.Equal(string.Empty, result); + } + } +} diff --git a/src/BCLExtensions.Tests/StringExtensions/SafeTrimTests.cs b/src/BCLExtensions.Tests/StringExtensions/SafeTrimTests.cs new file mode 100644 index 0000000..840dac1 --- /dev/null +++ b/src/BCLExtensions.Tests/StringExtensions/SafeTrimTests.cs @@ -0,0 +1,34 @@ +using Xunit; +using Xunit.Extensions; + +namespace BCLExtensions.Tests.StringExtensions +{ + public class SafeTrimTests + { + [Theory] + [InlineData("", "")] + [InlineData("Hello World", "Hello World")] + [InlineData("\nHello World\n", "Hello World")] + [InlineData("\tHello World\t", "Hello World")] + [InlineData(" Hello World ", "Hello World")] + [InlineData("Hello ", "Hello")] + [InlineData(" World", "World")] + [InlineData("Hello World", "Hello World")] + public void InputReturnsExpectedOutput(string input, string expected) + { + var result = input.SafeTrim(); + + Assert.Equal(expected, result); + } + + [Fact] + public void NullInputReturnsEmptyString() + { + string input = null; + + var result = input.SafeTrim(); + + Assert.Equal(string.Empty, result); + } + } +} diff --git a/src/BCLExtensions.Tests/StringExtensions/UnquotedTests.cs b/src/BCLExtensions.Tests/StringExtensions/UnquotedTests.cs new file mode 100644 index 0000000..0372d56 --- /dev/null +++ b/src/BCLExtensions.Tests/StringExtensions/UnquotedTests.cs @@ -0,0 +1,278 @@ +using Xunit; +// ReSharper disable ExpressionIsAlwaysNull + +namespace BCLExtensions.Tests.StringExtensions +{ + public class UnquotedTests + { + [Fact] + public void NullReturnsNull() + { + string input=null; + + var output = input.Unquoted(); + + Assert.Equal(input, output); + } + + [Fact] + public void EmptyStringReturnsEmpty() + { + string input = string.Empty; + + var output = input.Unquoted(); + + Assert.Equal(string.Empty, output); + } + + [Fact] + public void UnquotedStringReturnsOriginalString() + { + const string input = "This string has no quotes"; + + var output = input.Unquoted(); + + Assert.Equal(input, output); + } + + [Fact] + public void StringContainingOneQuoteReturnsOriginalString() + { + const string input = "This string has no \" characters surrounding it"; + + var output = input.Unquoted(); + + Assert.Equal(input, output); + } + + [Fact] + public void StringWithEmbeddedQuotesReturnsOriginalString() + { + const string input = "This string has no \"quotes\" surrounding it"; + + var output = input.Unquoted(); + + Assert.Equal(input, output); + } + + [Fact] + public void StringWithQuotesReturnsWithoutQuotes() + { + const string input = "\"This string has quotes surrounding it\""; + + var output = input.Unquoted(); + + Assert.Equal("This string has quotes surrounding it", output); + } + + [Fact] + public void StringWithTwoSetsOfQuotesReturnsWithoutOneSetOfQuotes() + { + const string input = "\"\"This string has quotes surrounding it\"\""; + + var output = input.Unquoted(); + + Assert.Equal("\"This string has quotes surrounding it\"", output); + } + + [Fact] + public void StringWithSurroundingAndEmbeddedQuotesReturnsWithoutQuotesWithEmbedded() + { + const string input = "\"This string has no \"quotes\" surrounding it\""; + + var output = input.Unquoted(); + + Assert.Equal("This string has no \"quotes\" surrounding it", output); + } + + [Fact] + public void StringContainingSurroundingQuotesAndOneQuoteReturnsWithoutSurroundingQuotes() + { + const string input = "\"This string has no \" characters surrounding it\""; + + var output = input.Unquoted(); + + Assert.Equal("This string has no \" characters surrounding it", output); + } + + [Fact] + public void QuotesOnlyStringBecomesEmptyString() + { + const string input = "\"\""; + + var output = input.Unquoted(); + + Assert.Equal(string.Empty, output); + } + + [Fact] + public void QuoteCharacterStringReturnsOriginalString() + { + const string input = "\""; + + var output = input.Unquoted(); + + Assert.Equal(input, output); + } + + [Fact] + public void StringContainingOneSingleQuoteReturnsOriginalString() + { + const string input = "This string has no \' characters surrounding it"; + + var output = input.Unquoted(); + + Assert.Equal(input, output); + } + + [Fact] + public void StringWithEmbeddedSingleQuotesReturnsOriginalString() + { + const string input = "This string has no \'quotes\' surrounding it"; + + var output = input.Unquoted(); + + Assert.Equal(input, output); + } + + [Fact] + public void StringWithSingleQuotesReturnsWithoutSingleQuotes() + { + const string input = "\'This string has quotes surrounding it\'"; + + var output = input.Unquoted(); + + Assert.Equal("This string has quotes surrounding it", output); + } + + [Fact] + public void StringWithTwoSetsOfSingleQuotesReturnsWithoutOneSetOfSingleQuotes() + { + const string input = "\'\'This string has quotes surrounding it\'\'"; + + var output = input.Unquoted(); + + Assert.Equal("\'This string has quotes surrounding it\'", output); + } + + [Fact] + public void StringWithSurroundingAndEmbeddedSingleQuotesReturnsWithoutSingleQuotesWithEmbedded() + { + const string input = "\'This string has no \'quotes\' surrounding it\'"; + + var output = input.Unquoted(); + + Assert.Equal("This string has no \'quotes\' surrounding it", output); + } + + [Fact] + public void StringContainingSurroundingSingleQuotesAndSingleQuoteReturnsWithoutSurroundingSingleQuotes() + { + const string input = "\'This string has no \' characters surrounding it\'"; + + var output = input.Unquoted(); + + Assert.Equal("This string has no \' characters surrounding it", output); + } + + [Fact] + public void SingleQuotesOnlyStringBecomesEmptyString() + { + const string input = "\'\'"; + + var output = input.Unquoted(); + + Assert.Equal(string.Empty, output); + } + + [Fact] + public void SingleQuoteCharacterStringReturnsOriginalString() + { + const string input = "\'"; + + var output = input.Unquoted(); + + Assert.Equal(input, output); + } + + [Fact] + public void StringWithSingleWrappingDoubleQuotesReturnsWithoutOneSetOfDoubleQuotes() + { + const string input = "\'\"This string has quotes surrounding it\"\'"; + + var output = input.Unquoted(); + + Assert.Equal("\"This string has quotes surrounding it\"", output); + } + + [Fact] + public void StringWithDoubleWrappingSingleQuotesReturnsWithoutOneSetOfSingleQuotes() + { + const string input = "\"\'This string has quotes surrounding it\'\""; + + var output = input.Unquoted(); + + Assert.Equal("\'This string has quotes surrounding it\'", output); + } + + [Fact] + public void StringWithSurroundingSingleQuotesAndEmbeddedQuotesReturnsWithoutSingleQuotesWithEmbedded() + { + const string input = "\'This string has no \"quotes\" surrounding it\'"; + + var output = input.Unquoted(); + + Assert.Equal("This string has no \"quotes\" surrounding it", output); + } + + [Fact] + public void StringWithSurroundingQuotesAndEmbeddedSingleQuotesReturnsWithoutQuotesWithEmbedded() + { + const string input = "\"This string has no \'quotes\' surrounding it\""; + + var output = input.Unquoted(); + + Assert.Equal("This string has no \'quotes\' surrounding it", output); + } + + [Fact] + public void StringContainingSurroundingSingleQuotesAndDoubleQuoteReturnsWithoutSurroundingSingleQuotes() + { + const string input = "\'This string has no \" characters surrounding it\'"; + + var output = input.Unquoted(); + + Assert.Equal("This string has no \" characters surrounding it", output); + } + + [Fact] + public void StringContainingSurroundingQuotesAndOneSingleQuoteReturnsWithoutSurroundingQuotes() + { + const string input = "\"This string has no \' characters surrounding it\""; + + var output = input.Unquoted(); + + Assert.Equal("This string has no \' characters surrounding it", output); + } + + [Fact] + public void StringWithSingleAndDoubleQuotesTransposedReturnsOriginalString() + { + const string input = "\'\"This string has quotes surrounding it\'\""; + + var output = input.Unquoted(); + + Assert.Equal(input, output); + } + + [Fact] + public void StringWithSingleAndDoubleQuotesTransposedTheOtherWayReturnsOriginalString() + { + const string input = "\"\'This string has quotes surrounding it\"\'"; + + var output = input.Unquoted(); + + Assert.Equal(input, output); + } + } +} diff --git a/src/BCLExtensions.sln.GhostDoc.xml b/src/BCLExtensions.sln.GhostDoc.xml new file mode 100644 index 0000000..0c987e9 --- /dev/null +++ b/src/BCLExtensions.sln.GhostDoc.xml @@ -0,0 +1,6 @@ + + + *.min.js + jquery*.js + + diff --git a/src/BCLExtensions/ActionExtensions.cs b/src/BCLExtensions/ActionExtensions.cs new file mode 100644 index 0000000..aa3f1a0 --- /dev/null +++ b/src/BCLExtensions/ActionExtensions.cs @@ -0,0 +1,52 @@ +using System; + +namespace BCLExtensions +{ + /// + /// Extension methods for the class. + /// + public static class ActionExtensions + { + /// + /// Extension method to expose a as an . + /// + /// The type of the parameter. + /// The action. + /// The parameter. + /// + public static Action AsActionUsing(this Action action, TParameter parameter) + { + return () => action(parameter); + } + + /// + /// Extension method to expose a as an . + /// + /// The type of parameter1. + /// The type of parameter2. + /// The action. + /// The parameter1. + /// The parameter2. + /// + public static Action AsActionUsing(this Action action, TParameter1 parameter1, TParameter2 parameter2) + { + return () => action(parameter1, parameter2); + } + + /// + /// Extension method to expose a as an . + /// + /// The type of parameter1. + /// The type of parameter2. + /// The type of parameter3. + /// The action. + /// The parameter1. + /// The parameter2. + /// The parameter3. + /// + public static Action AsActionUsing(this Action action, TParameter1 parameter1, TParameter2 parameter2, TParameter3 parameter3) + { + return () => action(parameter1, parameter2, parameter3); + } + } +} diff --git a/src/BCLExtensions/ArrayExtensions.cs b/src/BCLExtensions/ArrayExtensions.cs index fe657af..5d1ed80 100644 --- a/src/BCLExtensions/ArrayExtensions.cs +++ b/src/BCLExtensions/ArrayExtensions.cs @@ -8,11 +8,22 @@ namespace BCLExtensions /// public static class ArrayExtensions { + /// + /// Sets all the elements in an array to zero, false, or null, depending on their default. + /// + /// + /// The items. public static void Clear(this T[] items) { Array.Clear(items, 0, items.Length); } + /// + /// Ensures the array result either has items, or references null. + /// + /// + /// The items. + /// null if items is empty or null, otherwise the array is returned. public static T[] OrNullIfEmpty(this T[] items) { if (items != null && items.Any(i => i != null)) @@ -22,6 +33,12 @@ public static T[] OrNullIfEmpty(this T[] items) return null; } + /// + /// Ensures the array result is not null. + /// + /// + /// The items. + /// an empty array if null, otherwise the array is returned. public static T[] OrEmptyIfNull(this T[] items) { return items ?? new T[0]; diff --git a/src/BCLExtensions/BCLExtensions.csproj b/src/BCLExtensions/BCLExtensions.csproj index 632cb08..11daefc 100644 --- a/src/BCLExtensions/BCLExtensions.csproj +++ b/src/BCLExtensions/BCLExtensions.csproj @@ -25,6 +25,7 @@ prompt 4 true + bin\Debug\BCLExtensions.XML pdbonly @@ -34,12 +35,17 @@ prompt 4 true + bin\Release\BCLExtensions.XML + + + + diff --git a/src/BCLExtensions/ExclusiveInteger.cs b/src/BCLExtensions/ExclusiveInteger.cs new file mode 100644 index 0000000..212a827 --- /dev/null +++ b/src/BCLExtensions/ExclusiveInteger.cs @@ -0,0 +1,30 @@ +namespace BCLExtensions +{ + /// + /// Represents a semantically inclusive integer. + /// + public struct ExclusiveInteger + { + private readonly int _value; + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public ExclusiveInteger(int value) + { + _value = value; + } + + /// + /// Gets or sets the value. + /// + /// + /// The value. + /// + public int Value + { + get { return _value; } + } + } +} \ No newline at end of file diff --git a/src/BCLExtensions/FuncExtensions.cs b/src/BCLExtensions/FuncExtensions.cs index 655c17d..b6c6182 100644 --- a/src/BCLExtensions/FuncExtensions.cs +++ b/src/BCLExtensions/FuncExtensions.cs @@ -2,22 +2,66 @@ namespace BCLExtensions { + /// + /// Extension methods for the class. + /// public static class FuncExtensions { + /// + /// Extension method to expose a as an . + /// + /// + /// The function. + /// public static Action AsAction(this Func function) { return () => function(); } + /// + /// Extension method to expose a as an . + /// + /// The type of the output. + /// The type of the parameter. + /// The function. + /// The parameter. + /// public static Action AsActionUsing(this Func function, TParameter parameter) { return () => function(parameter); } - + /// + /// Extension method to expose a as an . + /// + /// The type of the output. + /// The type of parameter1. + /// The type of parameter2. + /// The function. + /// The parameter1. + /// The parameter2. + /// public static Action AsActionUsing(this Func function, TParameter1 parameter1, TParameter2 parameter2) { return () => function(parameter1, parameter2); } + + + /// + /// Extension method to expose a as an . + /// + /// The type of the output. + /// The type of parameter1. + /// The type of parameter2. + /// The type of parameter3. + /// The function. + /// The parameter1. + /// The parameter2. + /// The parameter3. + /// + public static Action AsActionUsing(this Func function, TParameter1 parameter1, TParameter2 parameter2, TParameter3 parameter3) + { + return () => function(parameter1, parameter2, parameter3); + } } } diff --git a/src/BCLExtensions/IEnumerableExtensions.cs b/src/BCLExtensions/IEnumerableExtensions.cs index 36d94f0..4a5736c 100644 --- a/src/BCLExtensions/IEnumerableExtensions.cs +++ b/src/BCLExtensions/IEnumerableExtensions.cs @@ -7,7 +7,7 @@ namespace BCLExtensions { /// - /// Extension methods for the class. + /// Extension methods for the class. /// public static class IEnumerableExtensions { diff --git a/src/BCLExtensions/InclusiveInteger.cs b/src/BCLExtensions/InclusiveInteger.cs new file mode 100644 index 0000000..4c8d856 --- /dev/null +++ b/src/BCLExtensions/InclusiveInteger.cs @@ -0,0 +1,30 @@ +namespace BCLExtensions +{ + /// + /// Represents a semantically inclusive integer. + /// + public struct InclusiveInteger + { + private readonly int _value; + + /// + /// Initializes a new instance of the struct. + /// + /// The value. + public InclusiveInteger(int value) + { + _value = value; + } + + /// + /// Gets or sets the value. + /// + /// + /// The value. + /// + public int Value + { + get { return _value; } + } + } +} \ No newline at end of file diff --git a/src/BCLExtensions/IntExtensions.cs b/src/BCLExtensions/IntExtensions.cs new file mode 100644 index 0000000..eb3c855 --- /dev/null +++ b/src/BCLExtensions/IntExtensions.cs @@ -0,0 +1,126 @@ +using System; + +namespace BCLExtensions +{ + /// + /// Extension methods for the class. + /// + public static class IntExtensions + { + /// + /// Ensures the order where first is less than or equal to the second. + /// + /// The first number. + /// The second number. + /// The second cannot be less than the first. + public static void EnsureOrder(int first, int second) + { + if (second < first) throw new InvalidOperationException("The first value {0} cannot be larger than the second value {1}.".FormatWith(first, second)); + } + + /// + /// Creates an . + /// + /// The value. + /// + public static InclusiveInteger Inclusive(this int value) + { + return new InclusiveInteger(value); + } + + /// + /// Creates an . + /// + /// The value. + /// + public static ExclusiveInteger Exclusive(this int value) + { + return new ExclusiveInteger(value); + } + + /// + /// Determines whether the value is between the specified limits. + /// + /// The value. + /// The lower limit. + /// The upper limit. + /// true is value is between lower and upper limit, otherwise false. + /// When lowerLimit is greater than upperLimit. + public static bool IsBetween(this int value, ExclusiveInteger lowerLimit, ExclusiveInteger upperLimit) + { + EnsureOrder(lowerLimit.Value, upperLimit.Value); + return lowerLimit.Value < value && value < upperLimit.Value; + } + + /// + /// Determines whether the value is between the specified limits. + /// + /// The value. + /// The lower limit. + /// The upper limit. + /// true is value is between lower (inclusive) and upper limit, otherwise false. + /// When lowerLimit is greater than upperLimit. + public static bool IsBetween(this int value, InclusiveInteger lowerLimit, ExclusiveInteger upperLimit) + { + EnsureOrder(lowerLimit.Value, upperLimit.Value); + return lowerLimit.Value <= value && value < upperLimit.Value; + } + + /// + /// Determines whether the value is between the specified limits. + /// + /// The value. + /// The lower limit. + /// The upper limit. + /// true is value is between lower and upper limit (inclusive), otherwise false. + /// When lowerLimit is greater than upperLimit. + public static bool IsBetween(this int value, ExclusiveInteger lowerLimit, InclusiveInteger upperLimit) + { + EnsureOrder(lowerLimit.Value, upperLimit.Value); + return lowerLimit.Value < value && value <= upperLimit.Value; + } + + /// + /// Determines whether the value is between the specified limits. + /// + /// The value. + /// The lower limit. + /// The upper limit. + /// true is value is between lower (inclusive) and upper limit (inclusive), otherwise false. + /// When lowerLimit is greater than upperLimit. + public static bool IsBetween(this int value, InclusiveInteger lowerLimit, InclusiveInteger upperLimit) + { + EnsureOrder(lowerLimit.Value, upperLimit.Value); + return lowerLimit.Value <= value && value <= upperLimit.Value; + } + + /// + /// Determines whether the value is inclusively between the lower and upper limit. + /// + /// The value. + /// The lower limit. + /// The upper limit. + /// true is value is between or equal to lower and upper limit, otherwise false. + /// When lowerLimit is greater than upperLimit. + public static bool IsBetween(this int value, int lowerLimit, int upperLimit) + { + EnsureOrder(lowerLimit, upperLimit); + return lowerLimit <= value && value <= upperLimit; + } + + /// + /// Determines whether the value is between the lower and upper limit (exclusive). + /// + /// The value. + /// The lower limit. + /// The upper limit. + /// true is value is between lower and upper limit, otherwise false. + /// When lowerLimit is greater than upperLimit. + public static bool IsBetweenExclusive(this int value, int lowerLimit, int upperLimit) + { + EnsureOrder(lowerLimit, upperLimit); + return lowerLimit < value && value < upperLimit; + } + + } +} diff --git a/src/BCLExtensions/ObjectExtensions.cs b/src/BCLExtensions/ObjectExtensions.cs index 455dd63..3c51ffe 100644 --- a/src/BCLExtensions/ObjectExtensions.cs +++ b/src/BCLExtensions/ObjectExtensions.cs @@ -3,15 +3,15 @@ namespace BCLExtensions { /// - /// Extension methods for the class. + /// Extension methods for the class. /// public static class ObjectExtensions { /// - /// Ensures that the instance is not null, or throws an exception + /// Ensures that the instance is not null, or throws an exception. /// - /// The object to verify - /// thrown when instance is null + /// The object to verify. + /// Thrown when instance is null. public static void EnsureIsNotNull(this object instance) { if (instance.IsNull()) @@ -19,13 +19,13 @@ public static void EnsureIsNotNull(this object instance) throw new ArgumentNullException(); } } - + /// - /// Ensures that the instance is not null, or throws an exception + /// Ensures that the instance is not null, or throws an exception. /// - /// The object to verify - /// The argumentName to use when expception is thrown - /// thrown when argumentName is null, or instance is null + /// The object to verify. + /// The argumentName to use when exception is thrown. + /// Thrown when argumentName is null, or instance is null. public static void EnsureIsNotNull(this object instance, string argumentName) { if (instance.IsNull()) @@ -35,20 +35,20 @@ public static void EnsureIsNotNull(this object instance, string argumentName) } /// - /// Checks whether the instance provided is not null + /// Checks whether the instance provided is not null. /// - /// The instance to check - /// true if instance is not null; otherwise false + /// The instance to check. + /// true if instance is not null; otherwise false. public static bool IsNotNull(this object instance) { return instance != null; } /// - /// Checks whether the instance provided is null + /// Checks whether the instance provided is null. /// - /// The instance to check - /// true if instance is null; otherwise false + /// The instance to check. + /// true if instance is null; otherwise false. public static bool IsNull(this object instance) { return instance == null; diff --git a/src/BCLExtensions/StringExtensions.cs b/src/BCLExtensions/StringExtensions.cs index c8be1c1..efb615c 100644 --- a/src/BCLExtensions/StringExtensions.cs +++ b/src/BCLExtensions/StringExtensions.cs @@ -40,7 +40,158 @@ public static bool IsNullOrWhitespace(this string input) { return string.IsNullOrWhiteSpace(input); } - + + /// + /// Gets the left most characters from the input string to a given length. + /// + /// The input. + /// The length. + /// The substring from the left of the string. + /// When the input length is shorter than the requested length, the original string is returned. + /// Thrown when input is null. + /// Thrown when length is less than zero. + public static string Left(this string input, int length) + { + input.EnsureIsNotNull("input"); + if (length < 0) throw new ArgumentOutOfRangeException("length", "Length cannot be less than 0."); + return length >= input.Length + ? input + : input.Substring(0, length); + } + + /// + /// Gets the right most characters from the input string to a given length. + /// + /// The input. + /// The length. + /// The substring from the left of the string. + /// When the input length is shorter than the requested length, the original string is returned. + /// Thrown when input is null. + /// Thrown when length is less than zero. + public static string Right(this string input, int length) + { + input.EnsureIsNotNull("input"); + if(length < 0) throw new ArgumentOutOfRangeException("length", "Length cannot be less than 0."); + return length >= input.Length + ? input + : input.Substring(input.Length-length, length); + } + + /// + /// Gets the left most characters from the input string to a given length. + /// + /// The input. + /// The length. + /// The substring from the left of the string. + /// + /// When the input length is shorter than the requested length, the original string is returned. + /// When the input is null, the empty string is returned. + /// + /// Thrown when length is less than zero. + public static string SafeLeft(this string input, int length) + { + if (length < 0) throw new ArgumentOutOfRangeException("length", "Length cannot be less than 0."); + input = input ?? string.Empty; + return length >= input.Length + ? input + : input.Substring(0, length); + } + + /// + /// Gets the right most characters from the input string to a given length. + /// + /// The input. + /// The length. + /// The substring from the left of the string. + /// + /// When the input length is shorter than the requested length, the original string is returned. + /// When the input is null, the empty string is returned. + /// + /// Thrown when length is less than zero. + public static string SafeRight(this string input, int length) + { + if (length < 0) throw new ArgumentOutOfRangeException("length", "Length cannot be less than 0."); + input = input ?? string.Empty; + return length >= input.Length + ? input + : input.Substring(input.Length - length, length); + } + + /// + /// Performs the .ToString() call safely, returning Empty string when null. + /// + /// + /// The item. + /// The object's ToString() result, or the empty string if null; + public static string SafeToString(this T item) + { + return item == null ? string.Empty : item.ToString(); + } + + /// + /// Performs the .ToString() call safely, returning Empty string when null. + /// + /// + /// The item. + /// The string to use when item is null. + /// The object's ToString() result, or the empty string if null; + /// Thrown when nullString is null. + public static string SafeToString(this T item, string nullString) + { + nullString.EnsureIsNotNull("nullString"); + return item == null ? nullString : item.ToString(); + } + + /// + /// Safely removes all trailing and leading whitespace characters from the input. + /// + /// The input. + /// The whitespace trimmed string, or the empty string if input is null. + public static string SafeTrim(this string input) + { + return input == null ? string.Empty : input.Trim(); + } + + /// + /// Safely removes all the leading whitespace characters from the input. + /// + /// The input. + /// The whitespace trimmed string, or the empty string if input is null. + public static string SafeTrimStart(this string input) + { + return input == null ? string.Empty : input.TrimStart(); + } + + /// + /// Safely removes all the trailing whitespace characters from the input. + /// + /// The input. + /// The whitespace trimmed string, or the empty string if input is null. + public static string SafeTrimEnd(this string input) + { + return input == null ? string.Empty : input.TrimEnd(); + } + + /// + /// Removes surrounding double or single quotes from a string, if applicable. + /// + /// The string to process. + /// input with quotes removed if surrounded by quotes; otherwise original value is returned + public static string Unquoted(this string value) + { + if (value == null) return null; + if (value.Length < 2) return value; + + const char singleQuote = '\''; + const char doubleQuote = '"'; + if ((value[0] == doubleQuote && value[value.Length - 1] == doubleQuote) + || (value[0] == singleQuote && value[value.Length - 1] == singleQuote)) + { + return value.Substring(1, value.Length - 2); + } + return value; + } + /// /// Takes the input string and returns the same string, or empty string if null /// @@ -103,7 +254,7 @@ public static string ValueOrIfNullOrWhitespace(this string value, string replace /// Takes the input string and returns the same string, or null if the string /// has no non-whitespace characters /// - /// The string to process + /// The string to process /// input if it contains non-whitespace characters; otherwise null public static string ValueOrNullIfWhitespace(this string value) {