PropertyResolvers 0.0.9
dotnet add package PropertyResolvers --version 0.0.9
NuGet\Install-Package PropertyResolvers -Version 0.0.9
<PackageReference Include="PropertyResolvers" Version="0.0.9"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="PropertyResolvers" Version="0.0.9" />
<PackageReference Include="PropertyResolvers"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add PropertyResolvers --version 0.0.9
#r "nuget: PropertyResolvers, 0.0.9"
#:package PropertyResolvers@0.0.9
#addin nuget:?package=PropertyResolvers&version=0.0.9
#tool nuget:?package=PropertyResolvers&version=0.0.9
PropertyResolvers
A C# source generator that creates type-safe property resolver classes. Instead of using reflection at runtime to extract property values from objects, PropertyResolvers generates compile-time switch expressions that efficiently resolve property values across multiple types.
Installation
dotnet add package PropertyResolvers
Quick Start
- Add assembly-level attributes to specify which properties you want resolvers for:
using PropertyResolvers.Attributes;
[assembly: GeneratePropertyResolver("AccountId")]
[assembly: GeneratePropertyResolver("TenantId")]
- The generator automatically finds all types with matching properties and generates resolver classes:
// Generated code (AccountIdResolver.g.cs)
public static class AccountIdResolver
{
public static string? GetAccountId(object? obj) => obj switch
{
global::MyApp.Order x => x.AccountId.ToString(),
global::MyApp.Customer x => x.AccountId.ToString(),
global::MyApp.Invoice x => x.AccountId.ToString(),
_ => null
};
}
- Use the generated resolvers in your code:
var order = new Order { AccountId = "ACC-123" };
var customer = new Customer { AccountId = "ACC-456" };
var product = new Product { Name = "Widget" }; // No AccountId property
var id1 = AccountIdResolver.GetAccountId(order); // "ACC-123"
var id2 = AccountIdResolver.GetAccountId(customer); // "ACC-456"
var id3 = AccountIdResolver.GetAccountId(product); // null
Use Cases
- Multi-tenant applications: Extract
TenantIdfrom any entity without reflection - Audit logging: Consistently retrieve identifier properties across different entity types
- Event sourcing: Extract aggregate IDs from various event types
- API responses: Normalize property access across different DTO types
Configuration Options
Basic Usage
[assembly: GeneratePropertyResolver("AccountId")]
Namespace Filtering
Include only specific namespaces:
[assembly: GeneratePropertyResolver("AccountId", IncludeNamespaces = new[] { "MyApp.Domain", "MyApp.Entities" })]
Exclude specific namespaces:
[assembly: GeneratePropertyResolver("AccountId", ExcludeNamespaces = new[] { "System", "Microsoft" })]
Multiple Resolvers
You can generate resolvers for multiple properties:
[assembly: GeneratePropertyResolver("AccountId", ExcludeNamespaces = new[] { "System", "Microsoft" })]
[assembly: GeneratePropertyResolver("TenantId", ExcludeNamespaces = new[] { "System", "Microsoft" })]
[assembly: GeneratePropertyResolver("EntityId", ExcludeNamespaces = new[] { "System", "Microsoft" })]
Attribute Reference
GeneratePropertyResolverAttribute
| Parameter | Type | Description |
|---|---|---|
propertyName |
string |
(Required) The name of the property to generate a resolver for. Case-insensitive matching. |
IncludeNamespaces |
string[]? |
Only include types from these namespaces (prefix match). |
ExcludeNamespaces |
string[]? |
Exclude types from these namespaces (prefix match). |
Analyzer
The package includes an analyzer that detects duplicate property resolver definitions:
// PR001: Property resolver for 'AccountId' is already defined
[assembly: GeneratePropertyResolver("AccountId")]
[assembly: GeneratePropertyResolver("AccountId")] // Error: duplicate
Duplicate detection is case-insensitive, so "AccountId" and "accountid" are considered duplicates.
How It Works
- The generator scans all assembly-level
GeneratePropertyResolverattributes - For each attribute, it finds all classes and structs with a matching property name
- It generates a static resolver class with a switch expression that pattern-matches on the object type
- The generated code uses
global::prefixes to avoid namespace conflicts
Generated Code Location
The generated resolver classes are placed in a namespace matching your assembly name. For example, if your assembly is MyApp, the resolvers will be in the MyApp namespace.
Requirements
- .NET Standard 2.0 compatible (works with .NET Framework 4.7.2+ and .NET Core 2.0+)
- C# 9.0 or later (for switch expressions in generated code)
- Visual Studio 2022 17.0+ or compatible IDE with Roslyn 4.0+ support
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.