Skip to main content

PropertyResolvers by Tom Biddulph

NuGet / site data

Nuget GitHub last commit GitHub Repo stars

Details

Info

info

Name: PropertyResolvers

A source generator that creates property resolver classes for types with matching properties. Use assembly-level attributes to generate resolvers that can retrieve property values from objects at runtime.

Author: Tom Biddulph

NuGet: https://www.nuget.org/packages/PropertyResolvers/

You can find more details at https://github.com/tombiddulph/PropertyResolvers

Source: https://github.com/tombiddulph/PropertyResolvers

Author

note

Tom Biddulph Alt text

Original Readme

note

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
  1. Add assembly-level attributes to specify which properties you want resolvers for:
using PropertyResolvers.Attributes;

[assembly: GeneratePropertyResolver("AccountId")]
[assembly: GeneratePropertyResolver("TenantId")]
  1. 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
};
}
  1. 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 TenantId from 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

ParameterTypeDescription
propertyNamestring(Required) The name of the property to generate a resolver for. Case-insensitive matching.
IncludeNamespacesstring[]?Only include types from these namespaces (prefix match).
ExcludeNamespacesstring[]?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
  1. The generator scans all assembly-level GeneratePropertyResolver attributes
  2. For each attribute, it finds all classes and structs with a matching property name
  3. It generates a static resolver class with a switch expression that pattern-matches on the object type
  4. 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

About

note

Generating code for switch for property in C#

How to use

Example (source csproj, source files)

This is the CSharp Project that references PropertyResolvers

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="PropertyResolvers" Version="0.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="PropertyResolvers.Attributes" Version="0.0.9" />
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

</Project>

Generated Files

Those are taken from $(BaseIntermediateOutputPath)\GX

// <auto-generated/>
#nullable enable

namespace PropSwitch;

public static class NameResolver
{
public static string? GetName(object? obj) => obj switch
{
global::PropSwitch.Person x => x.Name.ToString(),
global::PropSwitch.College x => x.Name.ToString(),
_ => null
};

}

Useful

Download Example (.NET C#)

Share PropertyResolvers

https://ignatandrei.github.io/RSCG_Examples/v2/docs/PropertyResolvers

Category "EnhancementProject" has the following generators:

1 AssemblyMetadata Nuget GitHub Repo stars 2026-04-02

2 AssemblyMetadata.Generators Nuget GitHub Repo stars 2026-05-15

3 AssemblyVersionInfo Nuget GitHub Repo stars 2025-07-28

4 AutoInvoke.Generator Nuget GitHub Repo stars 2024-03-03

5 AutoSpectre NugetNuget GitHub Repo stars 2024-02-24

6 Bennewitz.Ninja.AutoVersioning Nuget GitHub Repo stars 2026-07-04

7 BuildInfo Nuget GitHub Repo stars 2024-01-20

8 Credfeto.Version.Information.Generator Nuget GitHub Repo stars 2024-11-05

9 Larcanum.GitInfo Nuget GitHub Repo stars 2025-01-17

10 LinqGen.Generator NugetNuget GitHub Repo stars 2024-03-04

11 Pekspro.BuildInformationGenerator Nuget GitHub Repo stars 2024-07-19

12 PlantUmlClassDiagramGenerator NugetNuget GitHub Repo stars 2024-02-20

13 PropertyResolvers Nuget GitHub Repo stars 2026-08-26

14 RSCG_AMS Nuget GitHub Repo stars 2023-04-16

15 RSCG_ExportDiagram Nuget GitHub Repo stars 2024-08-01

16 RSCG_FunctionsWithDI Nuget GitHub Repo stars 2023-04-16

17 RSCG_NameGenerator Nuget GitHub Repo stars 2024-08-25

18 RSCG_TimeBombComment Nuget GitHub Repo stars 2023-04-16

19 RSCG_Wait Nuget GitHub Repo stars 2024-02-21

20 ShadowWriterProjectInfo Nuget GitHub Repo stars 2025-07-27

21 ThisAssembly Nuget GitHub Repo stars 2023-04-16

22 ThisAssembly.Constants Nuget GitHub Repo stars 2024-07-18

23 ThisAssembly.Metadata Nuget GitHub Repo stars 2024-07-20

See category

EnhancementProject