INTRODUCTION · LINQ-SOURCEGENERATOReQuantic.Linq.SourceGeneratoreQuantic.Linq.SourceGenerator is the compile-time half of eQuantic.Linq: it writes the specifications, filters and sorters a marked class needs, with Roslyn.
Overview
Nothing is worked out by reflection while a request waits, so the cost moves to the build and the mistakes move to the compiler.It wants .NET 6 or later, sits beside the main package, and is configured by attribute: one on the class, one on each property that should get operators.
Install it
shell
dotnet add package eQuantic.Linq.SourceGenerator
What it does
No reflection at run timeEvery specification is written when you build, so the request pays nothing for working out what to query.
Mistakes while you typeWhat it generates are real members: they autocomplete, and a name that does not exist is a compile error rather than an empty result.
Configured by attributeTwo attributes: which classes to generate for, and which operators each property should get.
It fits what is already thereIt works with eQuantic.Linq, with Entity Framework, and with anything else that takes an expression.
No reflection at run timeEvery specification is written when you build, so the request pays nothing for working out what to query.
Mistakes while you typeWhat it generates are real members: they autocomplete, and a name that does not exist is a compile error rather than an empty result.
Configured by attributeTwo attributes: which classes to generate for, and which operators each property should get.
It fits what is already thereIt works with eQuantic.Linq, with Entity Framework, and with anything else that takes an expression.
Quick start
Reference it as a build dependency — It runs while you build and ships with nothing, which is what PrivateAssets is saying.
Mark what should be generated — The attribute on the class opts it in. The one on a property picks the operators that property is worth having.
C#
[GenerateSpecifications]public class Product{ public int Id { get; set; } [SpecProperty(FilterOperators = FilterOperator.Equals | FilterOperator.Contains)] public string Name { get; set; } = string.Empty; [SpecProperty(FilterOperators = FilterOperator.GreaterThan | FilterOperator.LessThan)] public decimal Price { get; set; }}
Use the members it wrote — They sit on the class you marked, so the query reads as a sentence about the model rather than about the table.
C#
var cheapCoffee = Product.Specifications .NameContains("coffee") .And(Product.Specifications.PriceLessThan(10m));var found = await _repository.GetAsync(cheapCoffee);
Public surface
NAMESPACE
PUBLIC SURFACE
GenerateSpecificationsAttribute
Marks a class the generator should write specifications for.
SpecPropertyAttribute
Says which filter operators one property should get.
FilterOperator
The operators a property can be given: equals, contains, starts with, greater than, and the rest.
Prefer reading code?
Every package is MIT and public, and the samples are copy-paste ready.