├── .gitignore
├── [Main]
├── Properties
│ └── AssemblyInfo.cs
├── Internal
│ ├── NullabilityAttributes.cs
│ ├── ContractsShim.cs
│ ├── ObsoleteMessages.cs
│ ├── Grouping.cs
│ └── ReSharperAnnotations.cs
├── PropertyInfoExtensions.cs
├── FormattableExtensions.cs
├── AssemblyExtensions.cs
├── DoubleExtensions.cs
├── MethodInfoExtensions.cs
├── DelegateExtensions.cs
├── StringBuilderExtensions.cs
├── ListExtensions.cs
├── CollectionExtensions.cs
├── [Main].csproj
├── DateTimeExtensions.cs
├── DictionaryExtensions.cs
├── TypeExtensions.cs
├── TypeInfoExtensions.cs
├── CustomAttributeProviderExtensions.cs
├── CharExtensions.cs
├── ArrayExtensions.cs
└── StringExtensions.cs
├── NuGet.Config
├── ReadMeGenerator
├── App.config
├── Properties
│ └── AssemblyInfo.cs
├── ReadMeGenerator.csproj
├── Program.cs
└── MarkdownGenerator.cs
├── .editorconfig
├── Tests
├── CompilationTests.cs
├── AssemblyExtensionsTests.cs
├── Tests.csproj
├── TypeExtensionsTests.cs
├── ListExtensionsTests.cs
├── DoubleExtensionsTests.cs
├── DelegateExtensionTests.cs
├── DateTimeExtensionsTests.cs
├── CollectionExtensionsTests.cs
├── StringExtensionsTests.cs
├── StringBuilderExtensionsTests.cs
├── DictionaryExtensionsTests.cs
├── ArrayExtensionsTests.cs
└── EnumerableExtensionsTests.cs
├── Tests.Compilation
├── Tests.Compilation.csproj
├── CompilerAssert.cs
├── EnumerableExtensionsTests.cs
├── StringExtensionsTests.cs
└── DictionaryExtensionsTests.cs
├── appveyor.yml
├── README.md
├── AshMind.Extensions.sln.DotSettings
└── AshMind.Extensions.sln
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | bin/
3 | obj/
4 | .vs/
5 | \#packages/
6 | *.suo
7 | *.user
8 | *.lock.json
9 | *.nupkg
10 |
--------------------------------------------------------------------------------
/[Main]/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | [assembly: AssemblyCopyright("Copyright © Andrey Shchekin 2007–2017")]
--------------------------------------------------------------------------------
/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ReadMeGenerator/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 4
7 | trim_trailing_whitespace = true
8 | insert_final_newline = false
9 |
10 | [*.csproj]
11 | indent_size = 2
--------------------------------------------------------------------------------
/Tests/CompilationTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace AshMind.Extensions.Tests
6 | {
7 | class CompilationTests
8 | {
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/[Main]/Internal/NullabilityAttributes.cs:
--------------------------------------------------------------------------------
1 | #if No_Nullability_Attributes
2 | // ReSharper disable once CheckNamespace
3 | namespace System.Diagnostics.CodeAnalysis
4 | {
5 | internal sealed class MaybeNullAttribute : Attribute {}
6 | }
7 | #endif
--------------------------------------------------------------------------------
/[Main]/Internal/ContractsShim.cs:
--------------------------------------------------------------------------------
1 | #if No_Contracts
2 | // ReSharper disable once CheckNamespace
3 | namespace System.Diagnostics.Contracts {
4 | internal class PureAttribute : Attribute {}
5 | internal static class Contract {
6 | [Conditional("_DO_NOT_COMPILE_")]
7 | public static void EndContractBlock() {}
8 | }
9 | }
10 | #endif
--------------------------------------------------------------------------------
/[Main]/Internal/ObsoleteMessages.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace AshMind.Extensions.Internal
7 | {
8 | internal static class ObsoleteMessages
9 | {
10 | public const string MethodWillBeRemovedInVersion4StaticConsistency = "This method will be removed in version 4 (most of the code everywhere is using a stitic call, this is too inconsistent).";
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Tests.Compilation/Tests.Compilation.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net4.0;net472;netcoreapp3.0
4 | AshMind.Extensions.Tests.Compilation
5 | AshMind.Extensions.Tests.Compilation
6 | 8
7 | enable
8 | true
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Tests.Compilation/CompilerAssert.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace AshMind.Extensions.Tests.Compilation
7 | {
8 | // The purpose of these is to see there are no unexpected compiler warnings/errors.
9 | // Note: project must be set to WarningAsError.
10 |
11 | public static class CompilerAssert
12 | {
13 | public static void Nullable(ref string? value)
14 | {
15 | }
16 |
17 | public static void NotNullable(object value)
18 | {
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Tests.Compilation/EnumerableExtensionsTests.cs:
--------------------------------------------------------------------------------
1 | using AshMind.Extensions;
2 | using System.Collections.Generic;
3 |
4 | namespace AshMind.Extensions.Tests.Compilation
5 | {
6 | public static class EnumerableExtensionsTests
7 | {
8 | public static void EmptyIfNull_AllowsNull()
9 | {
10 | var enumerable = (IEnumerable?)null;
11 | enumerable.EmptyIfNull();
12 | }
13 |
14 | public static void EmptyIfNull_ReturnsNotNullable()
15 | {
16 | CompilerAssert.NotNullable(new string[0].EmptyIfNull());
17 | }
18 |
19 | public static void Except_AllowsNullItem()
20 | {
21 | CompilerAssert.NotNullable(new string?[0].Except(null));
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: '{build}'
2 | configuration: Release
3 | image: Visual Studio 2019 Preview
4 |
5 | install:
6 | - ps: |-
7 | choco install dotnetcore-sdk --version 3.0.100-preview7-012821 --pre
8 |
9 | cache:
10 | - C:\Users\appveyor\AppData\Local\Temp\1\chocolatey\vcredist140 -> .appveyor.yml
11 | - C:\Users\appveyor\AppData\Local\Temp\1\chocolatey\dotnetcore-sdk -> .appveyor.yml
12 |
13 | before_build:
14 | - dotnet restore
15 |
16 | build_script:
17 | - dotnet build --configuration Release
18 |
19 | after_test:
20 | - dotnet pack [Main] --configuration Release --output .
21 |
22 | artifacts:
23 | - path: '*.nupkg'
24 |
25 | deploy:
26 | - provider: NuGet
27 | on:
28 | branch: /^(master|\d\.\d)$/
29 | api_key:
30 | secure: Tz4nbtNMTV00UjCtvQB7yiSC/F8BiSE5Iob9qb8QvO57jrwzFoBXIlcVV+fyTVwE
31 | artifact: /.*\.nupkg/
--------------------------------------------------------------------------------
/Tests.Compilation/StringExtensionsTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace AshMind.Extensions.Tests.Compilation
4 | {
5 | public static class StringExtensionsTests
6 | {
7 | [Obsolete("To be removed in v4.")]
8 | public static void IsNullOrEmpty_AllowsNull()
9 | {
10 | ((string?)null).IsNullOrEmpty();
11 | }
12 |
13 | [Obsolete("To be removed in v4.")]
14 | public static void IsNullOrWhiteSpace_AllowsNull()
15 | {
16 | ((string?)null).IsNullOrWhiteSpace();
17 | }
18 |
19 | public static void NullIfEmpty_AllowsNull()
20 | {
21 | ((string?)null).NullIfEmpty();
22 | }
23 |
24 | public static void NullIfEmpty_ReturnsNullable()
25 | {
26 | var value = "".NullIfEmpty();
27 | CompilerAssert.Nullable(ref value);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ReadMeGenerator/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyConfiguration("")]
9 | [assembly: AssemblyCompany("")]
10 | [assembly: AssemblyProduct("ReadMeGenerator")]
11 | [assembly: AssemblyTrademark("")]
12 |
13 | // Setting ComVisible to false makes the types in this assembly not visible
14 | // to COM components. If you need to access a type in this assembly from
15 | // COM, set the ComVisible attribute to true on that type.
16 | [assembly: ComVisible(false)]
17 |
18 | // The following GUID is for the ID of the typelib if this project is exposed to COM
19 | [assembly: Guid("27ca6604-d094-41c0-bca9-8857c656e836")]
20 |
--------------------------------------------------------------------------------
/Tests/AssemblyExtensionsTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using Xunit;
6 |
7 | namespace AshMind.Extensions.Tests {
8 | public class AssemblyExtensionsTests {
9 | [Fact]
10 | public void GetAssemblyFile_ReturnsFileBasedOnAssemblyLocation() {
11 | var assembly = Assembly.GetExecutingAssembly();
12 | var file = assembly.GetAssemblyFile();
13 |
14 | Assert.Equal(assembly.Location, file.FullName);
15 | }
16 |
17 | [Fact]
18 | public void GetAssemblyFileFromCodeBase_ReturnsFileBasedOnAssemblyCodeBase() {
19 | var assembly = Assembly.GetExecutingAssembly();
20 | var file = assembly.GetAssemblyFileFromCodeBase();
21 | var url = new Uri(assembly.EscapedCodeBase);
22 |
23 | Assert.Equal(url.LocalPath, file.FullName);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ReadMeGenerator/ReadMeGenerator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netcoreapp2.1
4 | ReadMeGenerator
5 | Exe
6 | ReadMeGenerator
7 | false
8 | false
9 | false
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Tests/Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netcoreapp2.0; net46
4 | AshMind.Extensions.Tests
5 | AshMind.Extensions.Tests
6 | 8
7 | enable
8 | true
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | $(DefineConstants); No_StringBuilder_AppendJoin
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Tests/TypeExtensionsTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xunit;
3 |
4 | namespace AshMind.Extensions.Tests {
5 | public class TypeExtensionsTests {
6 | #region Test Classes
7 | public interface IInterface {}
8 | public interface ISubInterface : IInterface { }
9 | public class ClassWithInterface : IInterface {}
10 | public class SubclassOfClassWithInterface : ClassWithInterface { }
11 | public class ClassWithSubInterface : ISubInterface { }
12 | public class ClassWithoutInterface {}
13 | #endregion
14 |
15 | [Theory]
16 | [InlineData(typeof(ClassWithInterface), true)]
17 | [InlineData(typeof(SubclassOfClassWithInterface), true)]
18 | [InlineData(typeof(ClassWithSubInterface), true)]
19 | [InlineData(typeof(ISubInterface), true)]
20 | [InlineData(typeof(IInterface), false)]
21 | [InlineData(typeof(ClassWithoutInterface), false)]
22 | public void HasInterface(Type type, bool expectedResult) {
23 | Assert.Equal(expectedResult, type.HasInterface());
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/[Main]/Internal/Grouping.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using JetBrains.Annotations;
6 |
7 | namespace AshMind.Extensions.Internal {
8 | internal sealed class Grouping : IGrouping {
9 | public TKey Key { get; }
10 | [NotNull] private readonly IEnumerable _elements;
11 |
12 | public Grouping(TKey key, [NotNull] IEnumerable elements) {
13 | Key = key;
14 | _elements = elements;
15 | }
16 |
17 | public static IGrouping Create(TKey key, [NotNull] IEnumerable elements) {
18 | return new Grouping(key, elements);
19 | }
20 |
21 | public IEnumerator GetEnumerator() {
22 | return _elements.GetEnumerator();
23 | }
24 |
25 | #region IEnumerable Members
26 |
27 | IEnumerator IEnumerable.GetEnumerator() {
28 | return _elements.GetEnumerator();
29 | }
30 |
31 | #endregion
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/[Main]/PropertyInfoExtensions.cs:
--------------------------------------------------------------------------------
1 | #if No_Property_SetValue_NoIndex
2 | using System;
3 | using System.Diagnostics.Contracts;
4 | using System.Reflection;
5 | using JetBrains.Annotations;
6 | using Contracts = System.Diagnostics.Contracts;
7 | using PureAttribute = JetBrains.Annotations.PureAttribute;
8 |
9 | namespace AshMind.Extensions {
10 | ///
11 | /// Provides a set of extension methods for operations on .
12 | ///
13 | public static class PropertyInfoExtensions {
14 | public static void SetValue([NotNull] this PropertyInfo property, [CanBeNull] object obj, [CanBeNull] object value) {
15 | if (property == null) throw new ArgumentNullException("property");
16 | Contract.EndContractBlock();
17 |
18 | property.SetValue(obj, value, null);
19 | }
20 |
21 | [Contracts.Pure] [Pure] [CanBeNull]
22 | public static object GetValue([NotNull] this PropertyInfo property, [CanBeNull] object obj) {
23 | if (property == null) throw new ArgumentNullException("property");
24 | Contract.EndContractBlock();
25 |
26 | return property.GetValue(obj, null);
27 | }
28 | }
29 | }
30 | #endif
31 |
--------------------------------------------------------------------------------
/ReadMeGenerator/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Reflection;
6 |
7 | namespace AshMind.Extensions.ReadMeGenerator {
8 | public static class Program {
9 | public static void Main(string[] args) {
10 | try {
11 | var readmePath = FindPathToReadMe();
12 | using (var stream = File.OpenWrite(readmePath))
13 | using (var writer = new StreamWriter(stream)) {
14 | new MarkdownGenerator().WriteTo(writer);
15 | }
16 | }
17 | catch (Exception ex) {
18 | FluentConsole.Red.Text(ex);
19 | }
20 | }
21 |
22 | private static string FindPathToReadMe() {
23 | var initialDirectory = new FileInfo(typeof(Program).GetTypeInfo().Assembly.Location).Directory;
24 |
25 | var directory = initialDirectory;
26 | while (!directory.EnumerateFiles("*.sln").Any()) {
27 | directory = directory.Parent;
28 | if (directory == null)
29 | throw new Exception("Could not find solution folder for path '" + initialDirectory.FullName + "'.");
30 | }
31 |
32 | return Path.Combine(directory.FullName, "README.md");
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/[Main]/FormattableExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using JetBrains.Annotations;
4 | using Contracts = System.Diagnostics.Contracts;
5 |
6 | namespace AshMind.Extensions {
7 | ///
8 | /// Provides a set of extension methods for operations on IFormattable{T}.
9 | ///
10 | public static class FormattableExtensions {
11 | ///
12 | /// Formats the value using the specified format provider.
13 | ///
14 | /// The value to be formatted.
15 | /// The provider to use to format the value.
16 | /// The in the specified format.
17 | [Contracts.Pure] [Pure]
18 | public static string ToString([NotNull] this IFormattable value, IFormatProvider provider) {
19 | return value.ToString(null, provider);
20 | }
21 |
22 | ///
23 | /// Formats the value using the invariant culture format provider.
24 | ///
25 | /// The value to be formatted.
26 | /// The , formatted using invariant culture format provider.
27 | [Contracts.Pure] [Pure]
28 | public static string ToInvariantString([NotNull] this IFormattable value) {
29 | return value.ToString(CultureInfo.InvariantCulture);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Tests/ListExtensionsTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 | using System.Linq.Expressions;
6 | using Xunit;
7 |
8 | #pragma warning disable xUnit1019 // https://github.com/xunit/xunit/issues/1897
9 |
10 | namespace AshMind.Extensions.Tests {
11 | public class ListExtensionsTests {
12 | public delegate IList ListFactory(params int[] values);
13 |
14 | [Theory]
15 | [MemberData(nameof(Lists))]
16 | public void InsertRange_WorksCorrectly(Expression factory) {
17 | var list = factory.Compile()(0, 1, 2, 3, 4);
18 | list.InsertRange(3, new[] { 21, 22, 23 });
19 |
20 | Assert.Equal(
21 | new[] { 0, 1, 2, 21, 22, 23, 3, 4 },
22 | list.ToArray()
23 | );
24 | }
25 |
26 | [Theory]
27 | [MemberData(nameof(Lists))]
28 | public void RemoveRange_WorksCorrectly(Expression factory) {
29 | var list = factory.Compile()(0, 1, 2, 3, 4);
30 | list.RemoveRange(1, 3);
31 |
32 | Assert.Equal(new[] { 0, 4 }, list.ToArray());
33 | }
34 |
35 | public static IEnumerable