General‑purpose .NET extensions for strings, collections, tree traversal, embedded resources and exception types.
$ dotnet add package JJ.Framework.Common.LegacyA mixed bag of general-purpose utilities with minimal dependencies. Later versions of this library split functionality into focused packages like JJ.Framework.Text, JJ.Framework.Collections, and JJ.Framework.Exceptions. This "prequel" version contains a little bit of everything: a version released in aid of releasing older legacy apps, still holding value. Now targets .NET 10 and .NET Standard for wide compatibility and tested with 💯% code coverage.
Contents
Left / Right
"12345".Left(2) = "12""12345".Right(2) = "45"FromTill
"12345".FromTill(2, 3) = "34"CutLeft / CutRight
"BlaLala".CutLeft("Bla") = "Lala""12345".CutRight(2) = "123"CutLeftUntil / CutRightUntil
"Path/to/file.txt".CutRightUntil("/") = "Path/to/""Hello world!".CutLeftUntil("world") = "world!"StartWithCap / StartWithLowerCase
"test".StartWithCap() = "Test""TEST".StartWithLowerCase() = "tEST"Split
params variant for delimiters:"apple-banana|cherry".Split("-", "|") = [ "apple", "banana", "cherry" ]SplitWithQuotation
"apple|~banana|split~|cherry".SplitWithQuotation("|", '~') = [ "apple", "banana|split", "cherry" ]RemoveExcessiveWhiteSpace
" This is a test. ".RemoveExcessiveWhiteSpace() = "This is a test."Replace
String.Replace variant with optional case-insensitive match:"HelloWORLD".Replace("world", "Universe", ignoreCase: true ) = "HelloUniverse"Distinct
myItems.Distinct(x => x.LastName);myItems.Distinct(x => new { x.FirstName, x.LastName });Except
myCollection.Except(myItem);Except method from .NET automatically does a distinct, which is something you do not always want.)Union
myCollection.Union(myItem);myItem.Union(myCollection);Add
myCollection.Add(1, 5, 12);AddRange
AddRange is a member of List<T>. Here is a variation for IList<T> to support more collection types.ForEach
ForEach method. Here you have an overload for IEnumerable<T> so you can use it for more collection types.AsEnumerable
LINQ:IEnumerable<int> myInts = 3.AsEnumerable();TrimAll
string[] trimmedTexts = myTexts.TrimAll()LINQ methods already allow you to process a whole collection of items in one blow. Process a whole tree of items in one blow? For many cases these Recursive Collection Extensions offer a one-line solution.
This line of code:
var allItems = myRootItems.UnionRecursive(x => x.Children);
Gives you a list of all the nodes in a tree structure like the following:
var root = new Item
{
Children = new[]
{
new Item()
new Item
{
Children = new[]
{
new Item()
}
},
new Item
{
Children = new[]
{
new Item(),
new Item(),
}
},
}
};
There is also a SelectRecursive method:
var allItemsExceptRoots = myRootItems.SelectRecursive(x => x.Children);
The difference with UnionRecursive is that SelectRecursive does not include the roots in the result collection.
Converts a single array to KeyValuePair or Dictionary, where the 1st item is a name, the 2nd a value, the 3rd a name, the 4th a value, etc. This can be useful to be able to specify name/value pairs as params (variable amount of arguments). For instance:
void MyMethod(params object[] namesAndValues)
{
var dictionary = KeyValuePairHelper.ConvertNamesAndValuesListToDictionary(namesAndValues);
...
}
Calling MyMethod looks like this:
MyMethod("Name1", 3, "Name2", 5, "Name3", 6);
2 exception types with subtle differences:
InvalidValueException
Invalid CustomerType value: 'Undefined'.throw new InvalidValueException(CustomerType.Undefined)ValueNotSupportedException
CustomerType value: 'Subscriber' is not supported.throw new ValueNotSupportedException(CustomerType.Subscriber)EmbeddedResourceHelper
Streams, bytes and strings.CultureHelper
ConfigurationHelper
System.Configuration was not available.KeyHelper
Dictionaries by concatenating values with a GUID separator in between.Found an issue? Let me know.