Une bibliothèque C# .NET 9.0 légère avec une API ConfigurationBuilder fluide pour le filtrage et tri dynamique
Superfilter est une bibliothèque C# puissante et légère qui permet le filtrage et tri dynamique sur les sources IQueryable. Construite pour les applications .NET 9.0 modernes, elle propose une nouvelle API ConfigurationBuilder fluide qui élimine le casting manuel, offrant des capacités de requête type-safe avec support IntelliSense pour les API web avec une intégration transparente d'Entity Framework.
Nouvelle API fluide qui élimine le casting manuel avec des mappings de propriétés type-safe
Vérification complète des types à la compilation avec support IntelliSense pour une meilleure DX
Support pour Equals, Contains, StartsWith, comparaisons de dates et plus
Intégration transparente avec Entity Framework Core et LINQ-to-Objects
Superfilter transforme les expressions de filtre JSON en requêtes LINQ, ce qui le rend parfait pour les API REST qui ont besoin de capacités de filtrage flexibles.
Définissez vos critères de filtre au format JSON
Passez les critères à Superfilter
Obtenez un résultat IQueryable filtré
1// ConfigurationBuilder API - Complete Example
2using Superfilter;
3
4[HttpPost("search")]
5public async Task<IActionResult> SearchUsers([FromBody] UserSearchRequest request)
6{
7 // 1. Create configuration with fluent, type-safe API
8 var superfilter = SuperfilterBuilder.For<User>()
9 .MapProperty("id", u => u.Id) // Required filter
10 .MapProperty("name", u => u.Name) // Simple property
11 .MapProperty("carBrandName", u => u.Car.Brand.Name) // Nested navigation
12 .MapProperty("bornDate", u => u.BornDate) // DateTime support
13 .MapProperty("isActive", u => u.IsActive) // Boolean support
14 .WithFilters(request.Filters) // Dynamic from client
15 .WithSorts(request.Sorts) // Dynamic from client
16 .Build();
17
18 // 2. Apply filtering and sorting
19 var query = _context.Users.AsQueryable();
20 query = superfilter.ApplyConfiguredFilters(query);
21 query = query.ApplySorting(superfilter);
22
23 // 3. Execute query
24 return Ok(await query.ToListAsync());
25}
26
27// Key Benefits:
28// ✅ No manual casting required
29// ✅ Type safety with compile-time checking
30// ✅ IntelliSense support
31// ✅ Handles any property type automatically
32// ✅ Support for nested navigation properties
Manual casting required with verbose syntax
1// Sans Superfilter - Code verbeux et répétitif
2var query = dbContext.Users.AsQueryable();
3
4if (!string.IsNullOrEmpty(nameFilter))
5{
6 query = nameOperator switch
7 {
8 "contains" => query.Where(u => u.Name.Contains(nameFilter)),
9 "equals" => query.Where(u => u.Name == nameFilter),
10 "startsWith" => query.Where(u => u.Name.StartsWith(nameFilter)),
11 "endsWith" => query.Where(u => u.Name.EndsWith(nameFilter)),
12 "notEquals" => query.Where(u => u.Name != nameFilter),
13 "notContains" => query.Where(u => !u.Name.Contains(nameFilter)),
14 "isEmpty" => query.Where(u => string.IsNullOrEmpty(u.Name)),
15 "isNotEmpty" => query.Where(u => !string.IsNullOrEmpty(u.Name)),
16 _ => query
17 };
18}
19
20if (!string.IsNullOrEmpty(emailFilter))
21{
22 query = emailOperator switch
23 {
24 "contains" => query.Where(u => u.Email.Contains(emailFilter)),
25 "equals" => query.Where(u => u.Email == emailFilter),
26 "startsWith" => query.Where(u => u.Email.StartsWith(emailFilter)),
27 "endsWith" => query.Where(u => u.Email.EndsWith(emailFilter)),
28 "notEquals" => query.Where(u => u.Email != emailFilter),
29 "notContains" => query.Where(u => !u.Email.Contains(emailFilter)),
30 "isEmpty" => query.Where(u => string.IsNullOrEmpty(u.Email)),
31 "isNotEmpty" => query.Where(u => !string.IsNullOrEmpty(u.Email)),
32 _ => query
33 };
34}
35
36if (!string.IsNullOrEmpty(countryFilter))
37{
38 query = countryOperator switch
39 {
40 "equals" => query.Where(u => u.Country == countryFilter),
41 "notEquals" => query.Where(u => u.Country != countryFilter),
42 "contains" => query.Where(u => u.Country.Contains(countryFilter)),
43 _ => query
44 };
45}
46
47if (ageFilter.HasValue)
48{
49 query = ageOperator switch
50 {
51 "equals" => query.Where(u => u.Age == ageFilter.Value),
52 "notEquals" => query.Where(u => u.Age != ageFilter.Value),
53 "greater" => query.Where(u => u.Age > ageFilter.Value),
54 "greaterOrEquals" => query.Where(u => u.Age >= ageFilter.Value),
55 "less" => query.Where(u => u.Age < ageFilter.Value),
56 "lessOrEquals" => query.Where(u => u.Age <= ageFilter.Value),
57 "between" => query.Where(u => u.Age >= minAge && u.Age <= maxAge),
58 "notBetween" => query.Where(u => u.Age < minAge || u.Age > maxAge),
59 _ => query
60 };
61}
62
63if (loginCountFilter.HasValue)
64{
65 query = loginCountOperator switch
66 {
67 "equals" => query.Where(u => u.LoginCount == loginCountFilter.Value),
68 "greater" => query.Where(u => u.LoginCount > loginCountFilter.Value),
69 "less" => query.Where(u => u.LoginCount < loginCountFilter.Value),
70 _ => query
71 };
72}
73
74if (scoreFilter.HasValue)
75{
76 query = scoreOperator switch
77 {
78 "equals" => query.Where(u => u.Score == scoreFilter.Value),
79 "notEquals" => query.Where(u => u.Score != scoreFilter.Value),
80 _ => query
81 };
82}
83
84if (isActiveFilter.HasValue)
85{
86 query = query.Where(u => u.IsActive == isActiveFilter.Value);
87}
88
89if (isAdminFilter.HasValue)
90{
91 query = query.Where(u => u.IsAdmin == isAdminFilter.Value);
92}
93
94if (createdAtFilter.HasValue)
95{
96 query = createdAtOperator switch
97 {
98 "before" => query.Where(u => u.CreatedAt < createdAtFilter.Value),
99 "after" => query.Where(u => u.CreatedAt > createdAtFilter.Value),
100 "equals" => query.Where(u => u.CreatedAt.Date == createdAtFilter.Value.Date),
101 "notEquals" => query.Where(u => u.CreatedAt.Date != createdAtFilter.Value.Date),
102 "between" => query.Where(u => u.CreatedAt >= minCreatedAt && u.CreatedAt <= maxCreatedAt),
103 _ => query
104 };
105}
106
107if (moneyAmountFilter.HasValue)
108{
109 query = moneyAmountOperator switch
110 {
111 "equals" => query.Where(u => u.MoneyAmount == moneyAmountFilter.Value),
112 "greater" => query.Where(u => u.MoneyAmount > moneyAmountFilter.Value),
113 "less" => query.Where(u => u.MoneyAmount < moneyAmountFilter.Value),
114 "between" => query.Where(u => u.MoneyAmount >= minAmount && u.MoneyAmount <= maxAmount),
115 _ => query
116 };
117}
118
119// ... répéter pour chaque propriété
120var result = query.ToList();
Clean, type-safe ConfigurationBuilder API
1// New ConfigurationBuilder API - Type-safe & Clean
2[HttpPost("search")]
3public async Task<IActionResult> SearchUsers([FromBody] UserSearchRequest request)
4{
5 // 1. Create configuration with clean, type-safe property mappings
6 var superfilter = SuperfilterBuilder.For<User>()
7 .MapRequiredProperty(u => u.Id) // No casting required!
8 .MapProperty(u => u.Car.Brand.Name) // Nested navigation supported
9 .MapProperty(u => u.Name) // IntelliSense support
10 .MapProperty(u => u.isAdmin)
11 // Add for each property you want it to be filterable
12 .WithFilters(request.Filters) // Dynamic filters from client
13 .WithSorts(request.Sorts) // Dynamic sorts from client
14 .Build();
15
16 // 2. Apply filtering and sorting
17 var query = _context.Users.AsQueryable();
18 query = superfilter.ApplyConfiguredFilters(query);
19 query = query.ApplySorting(superfilter);
20
21 // 3. Execute query
22 return Ok(await query.ToListAsync());
23}
Génère des expressions LINQ optimisées qui se traduisent en requêtes SQL efficaces
Syntaxe simple basée sur JSON qui est facile à comprendre et à implémenter
Dépendances minimales et empreinte réduite pour vos applications
Intellisense complet et sécurité à la compilation