Extensaur.Reflection 1.0.0

dotnet add package Extensaur.Reflection --version 1.0.0
                    
NuGet\Install-Package Extensaur.Reflection -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Extensaur.Reflection" Version="1.0.0">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Extensaur.Reflection" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Extensaur.Reflection">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Extensaur.Reflection --version 1.0.0
                    
#r "nuget: Extensaur.Reflection, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Extensaur.Reflection@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Extensaur.Reflection&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Extensaur.Reflection&version=1.0.0
                    
Install as a Cake Tool

Reflection Extensions

Source only package for Reflection - High-performance compiled expression-based reflection utilities for .NET

This package provides a comprehensive set of classes for high-performance reflection operations using compiled expressions instead of traditional reflection calls. The package is optimized for scenarios where reflection operations need to be performed repeatedly, such as ORM scenarios, object mapping, and dynamic property access.

Key Features

  • High Performance: Uses compiled expressions instead of traditional reflection for significantly better performance
  • Mapping Support: Built-in support for Data Annotations attributes
  • Type Safety: Strongly-typed interfaces and generic methods where possible
  • Caching: Intelligent caching of compiled expressions and member information
  • Late Binding: Dynamic member access with runtime type resolution
  • Comprehensive Coverage: Support for properties, fields, methods, and constructors

Core Classes

TypeAccessor

The main entry point for accessing type information and members. Provides high-performance reflection-based access to type members through compiled expressions.

// Get a type accessor
var accessor = TypeAccessor.GetAccessor<Person>();
var accessor = TypeAccessor.GetAccessor(typeof(Person));

// Create instances
var person = accessor.Create();

// Access properties
var nameAccessor = accessor.FindProperty("Name");
nameAccessor.SetValue(person, "John Doe");
var name = nameAccessor.GetValue(person);

// Access by database column name
var columnAccessor = accessor.FindColumn("first_name");

// Get all properties
var properties = accessor.GetProperties();

// Find methods
var methodAccessor = accessor.FindMethod("ToString");
var result = methodAccessor.Invoke(person);

Key Features:

  • Static caching of accessors per type for optimal performance
  • Support for TableAttribute for database table mapping
  • Expression-based property finding with compile-time safety
  • Intelligent method overload resolution
  • Case-insensitive member searching as fallback

LateBinder

Static utility class providing simplified late-binding operations for dynamic member access.

// Set property/field values
LateBinder.SetProperty(person, "Name", "John Doe");
LateBinder.SetField(person, "_id", 123);

// Tries property first, then field
LateBinder.Set(person, "Email", "john@example.com"); 

// Get property/field values  
var name = LateBinder.GetProperty(person, "Name");
var id = LateBinder.GetField(person, "_id");

// Tries property first, then field
var email = LateBinder.Get(person, "Email");

// Create instances
var instance = LateBinder.CreateInstance(typeof(Person));

// Invoke methods
var result = LateBinder.InvokeMethod(person, "ToString");

// Static method
var result = LateBinder.InvokeMethod(typeof(Math), null, "Abs", -5);

// Find members
var propertyAccessor = LateBinder.FindProperty(typeof(Person), "Name");
var methodAccessor = LateBinder.FindMethod(typeof(Person), "ToString");

Key Features:

  • Unified API for common reflection operations
  • Support for nested property access with dot notation
  • Automatic type resolution and method overload matching
  • Both public and non-public member access options
  • Static and instance method support

IMemberAccessor Interface

Provides a unified interface for accessing different types of members (properties and fields).

public interface IMemberAccessor : IMemberInformation
{
    object? GetValue(object? instance);
    void SetValue(object? instance, object? value);
}

Implementations:

  • PropertyAccessor - For property access
  • FieldAccessor - For field access

PropertyAccessor

Specialized accessor for properties with high-performance compiled expression-based access.

var typeAccessor = TypeAccessor.GetAccessor<Person>();
var accessor = typeAccessor.FindProperty("Name");

// High-performance property access
accessor.SetValue(person, "John Doe");
var name = accessor.GetValue(person);

Key Features:

  • Lazy-loaded compiled expressions for optimal performance
  • Support for both readable and writable properties
  • Handles static and instance properties
  • Efficient null handling and type casting

FieldAccessor

Specialized accessor for fields with high-performance compiled expression-based access.

var typeAccessor = TypeAccessor.GetAccessor<Person>();
var accessor = typeAccessor.FindField("_name");

// High-performance field access
accessor.SetValue(person, "John Doe");
var name = accessor.GetValue(person);

Key Features:

  • Handles readonly and const field restrictions
  • Support for both public and private fields
  • Efficient expression compilation and caching
  • Static and instance field support

IMethodAccessor Interface & MethodAccessor

High-performance method invocation through compiled expressions.

public interface IMethodAccessor
{
    MethodInfo MethodInfo { get; }
    string Name { get; }
    object? Invoke(object? instance, params object?[] arguments);
}

var methodInfo = typeof(Person).GetMethod("ToString");
var accessor = new MethodAccessor(methodInfo);

// High-performance method invocation
var result = accessor.Invoke(person);
var result = accessor.Invoke(person, arg1, arg2); // With arguments

Key Features:

  • Compiled expressions for fast method invocation
  • Automatic parameter validation and type conversion
  • Support for void and non-void return types
  • Static and instance method support
  • Intelligent method overload resolution

IMemberInformation Interface

Comprehensive interface providing member metadata including database mapping information.

public interface IMemberInformation
{
    Type MemberType { get; }
    MemberInfo MemberInfo { get; }
    string Name { get; }
    string Column { get; }
    string? ColumnType { get; }
    int? ColumnOrder { get; }
    bool IsKey { get; }
    bool IsNotMapped { get; }
    bool IsDatabaseGenerated { get; }
    bool IsConcurrencyCheck { get; }
    string? ForeignKey { get; }
    bool HasGetter { get; }
    bool HasSetter { get; }
}

Supported Data Annotations:

  • [Column] - Database column mapping
  • [Key] - Primary key identification
  • [NotMapped] - Exclude from database mapping
  • [DatabaseGenerated] - Database-generated values
  • [ConcurrencyCheck] - Optimistic concurrency control
  • [ForeignKey] - Foreign key relationships
  • [Table] - Table name and schema mapping

MemberAccessor (Abstract Base Class)

Abstract base class providing common functionality for member accessors including lazy-loaded Data Annotations attribute access.

Key Features:

  • Lazy-loaded attribute caching for performance
  • Base implementation of IMemberAccessor and IMemberInformation
  • Equality comparison based on underlying MemberInfo
  • Debugger-friendly display attributes

ExpressionFactory (Internal)

Internal factory class that creates compiled expressions for high-performance member access. This class handles the complex expression tree generation and compilation.

Capabilities:

  • Method invocation delegates with parameter validation
  • Property and field getter/setter delegates
  • Constructor delegates for object creation
  • Safe type casting and null handling
  • Optimized boxing for value types
  • Parameter count validation with helpful error messages

Usage Examples

Basic Property Access

// Get type accessor
var accessor = TypeAccessor.GetAccessor<Person>();

// Find and use property accessor  
var nameAccessor = accessor.FindProperty("Name");
nameAccessor.SetValue(person, "John Doe");
var name = nameAccessor.GetValue(person);

Database Mapping Scenarios

[Table("People", Schema = "dbo")]
public class Person
{
    [Key]
    public int Id { get; set; }
    
    [Column("first_name")]
    public string FirstName { get; set; }
    
    [Column("last_name")]  
    public string LastName { get; set; }
    
    [NotMapped]
    public string FullName => $"{FirstName} {LastName}";
    
    [ConcurrencyCheck]
    public byte[] RowVersion { get; set; }
}

var accessor = TypeAccessor.GetAccessor<Person>();

// Access by database column name
var firstNameAccessor = accessor.FindColumn("first_name");
firstNameAccessor.SetValue(person, "John");

// Get table information
Console.WriteLine($"Table: {accessor.TableName}");    // "People"  
Console.WriteLine($"Schema: {accessor.TableSchema}"); // "dbo"

// Check member attributes
var properties = accessor.GetProperties();
foreach (var prop in properties)
{
    Console.WriteLine($"{prop.Name}");
}

Expression-Based Property Access

var accessor = TypeAccessor.GetAccessor<Person>();

// Type-safe property access using expressions
var nameAccessor = accessor.FindProperty<Person, string>(p => p.Name);
nameAccessor.SetValue(person, "John Doe");

Method Invocation

var accessor = TypeAccessor.GetAccessor<Person>();

// Find and invoke method
var toStringMethod = accessor.FindMethod("ToString");
var result = toStringMethod.Invoke(person);

// Method with parameters
var equalsMethod = accessor.FindMethod("Equals", [typeof(object)]);  
var isEqual = equalsMethod.Invoke(person, otherPerson);

Late Binding Operations

// Simple property access
LateBinder.SetProperty(person, "Name", "John Doe");
var name = LateBinder.GetProperty(person, "Name");

// Unified member access (tries property first, then field)
LateBinder.Set(person, "Email", "john@example.com");
var email = LateBinder.Get(person, "Email");

// Method invocation with automatic overload resolution
var result = LateBinder.InvokeMethod(person, "CompareTo", otherPerson);

Performance Benefits

This package provides significant performance improvements over traditional reflection:

  • Compiled Expressions: Method calls are compiled to optimized delegates
  • Caching: Type accessors and member accessors are cached for reuse
  • Lazy Loading: Expensive operations are deferred until first use
  • Optimized Type Conversion: Smart handling of boxing/unboxing and type casting

Thread Safety

All classes in this package are designed to be thread-safe:

  • Static caches use ConcurrentDictionary for safe concurrent access
  • Lazy initialization ensures thread-safe single initialization
  • Compiled delegates are inherently thread-safe once created

Integration with ORMs

This package is designed to work well with Object-Relational Mapping scenarios:

  • Full support for Data Annotations
  • Database column name mapping and resolution
  • Primary key and foreign key relationship support
  • Concurrency token and database-generated value handling
  • Table and schema name resolution

The comprehensive metadata provided by IMemberInformation makes it ideal for building ORM tools, object mappers, serializers, and other data access libraries that need efficient member access combined with rich metadata

Compiler Configuration

PUBLIC_EXTENSIONS

By default, the classes in this package are marked as internal to avoid namespace pollution in consuming projects. If you need direct access to classes from outside the assembly, you can make them public by defining the PUBLIC_EXTENSIONS compiler constant.

Add the following to your project file (.csproj) to make the extension classes public:

<PropertyGroup>
  <DefineConstants>$(DefineConstants);PUBLIC_EXTENSIONS</DefineConstants>
</PropertyGroup>

When to use PUBLIC_EXTENSIONS:

  • You need direct access to extension classes from outside the assembly
  • You're building libraries that extend or wrap this functionality
  • You need to expose reflection utilities in your public API

Default behavior (without PUBLIC_EXTENSIONS):

  • All extension classes remain internal
  • Main functionality is still accessible through the public interfaces
  • Cleaner public API surface for most use cases

Language Version

This package uses modern C# language features and requires C# 11.0 or later. If your project doesn't build or you encounter compiler errors, ensure your project is configured to use the latest C# language version:

<PropertyGroup>
  <LangVersion>latest</LangVersion>
</PropertyGroup>

Why this is required:

  • The package uses modern C# features like file-scoped namespaces, global using statements, and improved pattern matching
  • Older C# language versions may not recognize these syntax features
  • Using latest ensures compatibility with the newest language features
There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

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.

Version Downloads Last Updated
1.0.0 589 9/25/2025