TrimItEasy by Phong Nguyen
NuGet / site data
Details
Info
Name: TrimItEasy
Package Description
Author: Phong Nguyen
NuGet: https://www.nuget.org/packages/TrimItEasy/
You can find more details at https://github.com/phongnguyend/TrimItEasy
Author
Phong Nguyen

Original Readme
TrimItEasy
A simple and efficient .NET library for automatically trimming string properties in complex objects.
Installation
Install the package from NuGet:
dotnet add package TrimItEasy
Or using the NuGet Package Manager in Visual Studio:
Install-Package TrimItEasy
Usage
######### Basic Usage
Simply call the TrimStrings() extension method on any complex object:
using TrimItEasy;
public class Person
{
public string Name \{ get; set; }
public string Email \{ get; set; }
public Address HomeAddress \{ get; set; }
}
var person = new Person
{
Name = " John Doe ",
Email = " john@example.com ",
HomeAddress = new Address
{
Street = " 123 Main St ",
City = " New York "
}
};
// Trim all string properties
person.TrimStrings();
######### Skip Trimming Specific Properties
Use the [NotTrimmed] attribute to prevent trimming of specific properties:
public class Address
{
[NotTrimmed]
public string Street \{ get; set; \} // This property will not be trimmed
public string City \{ get; set; \} // This property will be trimmed
}
var address = new Address
{
Street = " 123 Main St, Apt 4B ", // Will remain unchanged
City = " New York " // Will be trimmed to "New York"
};
address.TrimStrings();
######### Recursive Trimming
By default, the library recursively trims all string properties in nested objects up to a maximum depth of 64 levels. You can customize this behavior using TrimmingOptions:
// Only trim top-level string properties (disable recursion)
person.TrimStrings(new TrimmingOptions \{ Recursive = false });
// Limit recursion to 2 levels of nested objects
person.TrimStrings(new TrimmingOptions \{ MaxDepth = 2 });
// Only trim the top-level object's string properties (no nested objects)
person.TrimStrings(new TrimmingOptions \{ MaxDepth = 0 });
| Option | Type | Default | Description |
|---|---|---|---|
Recursive | bool | true | Whether to trim strings in nested objects. When false, only top-level string properties are trimmed. |
MaxDepth | int | 64 | Maximum depth for recursive trimming. 0 trims only top-level properties, 1 includes one level of nested objects, and so on. |
######### Supported Types
The library works with:
- Complex objects with string properties
- Collections (Lists, Arrays, etc.)
- Nested objects
- Properties marked with
[NotTrimmed]will be skipped
######### Limitations
The library will throw an ArgumentException if you try to use it on:
- String types (use
string.Trim()instead) - Primitive types
- Enum types
Examples
######### Working with Collections
public class Company
{
public string Name \{ get; set; }
public List<Employee> Employees \{ get; set; }
}
public class Employee
{
public string Name \{ get; set; }
[NotTrimmed]
public string EmployeeId \{ get; set; }
}
var company = new Company
{
Name = " Acme Corp ",
Employees = new List<Employee>
{
new Employee \{ Name = " John Doe ", EmployeeId = " E001 " },
new Employee \{ Name = " Jane Smith ", EmployeeId = " E002 " }
}
};
company.TrimStrings();
// Result:
// - company.Name = "Acme Corp"
// - company.Employees[0].Name = "John Doe"
// - company.Employees[0].EmployeeId = " E001 " (not trimmed due to [NotTrimmed])
######### Working with Nested Objects
public class Order
{
public string OrderNumber \{ get; set; }
public Customer Customer \{ get; set; }
public List<OrderItem> Items \{ get; set; }
}
public class Customer
{
public string Name \{ get; set; }
[NotTrimmed]
public string PhoneNumber \{ get; set; }
}
var order = new Order
{
OrderNumber = " ORD-001 ",
Customer = new Customer
{
Name = " John Doe ",
PhoneNumber = " +1 (555) 123-4567 "
},
Items = new List<OrderItem>
{
new OrderItem \{ Description = " Product A " }
}
};
order.TrimStrings();
// All string properties will be trimmed except Customer.PhoneNumber
######### Source Generator (Zero Reflection)
For maximum performance, TrimItEasy includes a source generator that produces optimized trimming code at compile time � no reflection at runtime.
########## Installation
Install both the core library and the source generator package:
dotnet add package TrimItEasy
dotnet add package TrimItEasy.Generators
Or using the NuGet Package Manager in Visual Studio:
Install-Package TrimItEasy
Install-Package TrimItEasy.Generators
Note: The
TrimItEasy.Generatorspackage must be referenced as an analyzer. If you are referencing the project directly, use:<ProjectReference Include="..\TrimItEasy.Generators\TrimItEasy.Generators.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
########## Usage
- Define a
static partialextension method that takes your target type as athisparameter and returnsvoid. - Annotate it with
[GeneratedTrimming].
The source generator will implement the method body automatically.
using TrimItEasy;
public class Person
{
public string Name \{ get; set; }
public string Email \{ get; set; }
public Address HomeAddress \{ get; set; }
public List<Phone> Phones \{ get; set; }
}
public class Address
{
public string Street \{ get; set; }
public string City \{ get; set; }
}
public class Phone
{
public string Type \{ get; set; }
public string Number \{ get; set; }
}
// Define the partial method � the source generator fills in the implementation
public static partial class PersonExtensions
{
[GeneratedTrimming]
public static partial void FastTrimStrings(this Person person);
[GeneratedTrimming]
public static partial void FastTrimStringsWithOptions(this Person person, TrimmingOptions? options = null);
}
Then simply call the generated method:
var person = new Person
{
Name = " John Doe ",
Email = " john@example.com ",
HomeAddress = new Address
{
Street = " 123 Main St ",
City = " New York "
},
Phones = new List<Phone>
{
new Phone \{ Type = " Mobile ", Number = " 123-456-7890 " }
}
};
person.FastTrimStrings();
// All string properties are trimmed, including nested objects and collections
########## How It Works
- The source generator analyzes the target type's property graph at compile time.
- It generates a dedicated trimming method that directly accesses each string property � no reflection involved.
- Nested objects and collections (
List<T>, arrays, etc.) are handled recursively. - Properties marked with
[NotTrimmed]are respected and skipped. - Circular references are detected and handled safely using a visited set.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
About
trimming eacg string from a class properties
How to use
Example (source csproj, source files)
- CSharp Project
- Program.cs
This is the CSharp Project that references TrimItEasy
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="TrimItEasy" Version="1.0.0" />
<PackageReference Include="TrimItEasy.Generators" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>
This is the use of TrimItEasy in Program.cs
using TrimDemo;
Person p = new();
p.FirstName = " Andrei ";
p.LastName = " Ignat ";
p.FastTrimStrings();
Console.WriteLine(p.FirstName + " " + p.LastName);
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- PersonExtensions_FastTrimStrings.g.cs
// <auto-generated />
#nullable enable
using System.Collections;
using System.Collections.Generic;
namespace TrimDemo;
public static partial class PersonExtensions
{
public static partial void FastTrimStrings(this global::TrimDemo.Person person)
{
var visited = new HashSet<object>(ReferenceEqualityComparer.Instance);
TrimProperties_TrimDemo_Person(person, visited);
}
private static void TrimProperties_TrimDemo_Person(global::TrimDemo.Person obj, HashSet<object> visited)
{
if (obj == null || !visited.Add(obj))
{
return;
}
if (obj.FirstName != null)
{
obj.FirstName = obj.FirstName.Trim();
}
if (obj.LastName != null)
{
obj.LastName = obj.LastName.Trim();
}
}
private static void TrimRecursive(object? obj, HashSet<object> visited)
{
if (obj == null || obj is string)
{
return;
}
var type = obj.GetType();
if (type.IsPrimitive || type.IsEnum || type == typeof(decimal) || type == typeof(System.DateTime) || type == typeof(System.DateTimeOffset))
{
return;
}
if (!type.IsValueType && !visited.Add(obj))
{
return;
}
if (obj is global::TrimDemo.Person typed_TrimDemo_Person)
{
TrimProperties_TrimDemo_Person(typed_TrimDemo_Person, visited);
return;
}
if (obj is IList list)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i] is string s)
{
list[i] = s.Trim();
}
else
{
TrimRecursive(list[i], visited);
}
}
return;
}
if (obj is IEnumerable enumerable)
{
foreach (var item in enumerable)
{
if (item is not string)
{
TrimRecursive(item, visited);
}
}
return;
}
}
}
Useful
Download Example (.NET C#)
Share TrimItEasy
https://ignatandrei.github.io/RSCG_Examples/v2/docs/TrimItEasy
Category "EnhancementClass" has the following generators:
1 ApparatusAOT
2023-04-16
2 AspectGenerator
2024-01-07
3 CommonCodeGenerator
2024-04-03
4 Comparison
2025-05-25
5 DudNet
2023-10-27
6 Enhanced.GetTypes
2024-09-17
7 FastGenericNew
2023-08-10
8 Immutype
2023-08-12
9 Ling.Audit
2023-12-12
10 Lombok.NET
2023-04-16
11 M31.FluentAPI
2023-08-25
12 MemberAccessor
2025-03-24
13 MemoryPack
2023-08-04
14 Meziantou.Polyfill
2023-10-10
15 Microsoft.Extensions.Logging
2023-04-16
16 Microsoft.Extensions.Options.Generators.OptionsValidatorGenerator
2023-11-17
17 Microsoft.Interop.JavaScript.JSImportGenerator 2023-04-16
18 NLog.Extensions.ThisClass
2026-04-03
19 OptionToStringGenerator
2024-02-15
20 Pekspro.DataAnnotationValuesExtractor
2026-02-15
21 Program
2025-11-06
22 QueryStringGenerator
2024-11-07
23 RSCG_Decorator
2023-09-30
24 RSCG_UtilityTypes
2023-12-22
25 StaticReflection
2023-10-13
26 SyncMethodGenerator
2023-08-14
27 System.Runtime.InteropServices
2023-04-16
28 System.Text.RegularExpressions
2023-04-16
29 TelemetryLogging
2023-11-30
30 ThisClass
2024-04-19
31 TrimItEasy
2026-08-28