Skip to content

Latest commit

 

History

History
146 lines (109 loc) · 5.37 KB

File metadata and controls

146 lines (109 loc) · 5.37 KB
layout default
title v0.5.0
description Release notes for Neatoo RemoteFactory v0.5.0
parent Release Notes
nav_order 2

v0.5.0 - Constructor Injection Compatibility

Release Date: 2026-01-04 NuGet: Neatoo.RemoteFactory 0.5.0

Overview

This release fixes compatibility with domain objects that require constructor-injected services (such as Neatoo EntityBase types). Types that cannot be instantiated via object initializer syntax now correctly skip ordinal serialization generation and fall back to named-property serialization.

What's New

Constructor Injection Detection

The source generator now analyzes constructors to determine if a type can be instantiated using object initializer syntax. Types that require constructor parameters (for dependency injection) automatically skip ordinal serialization generation.

Types that generate ordinal serialization:

  • Classes with parameterless constructors (implicit or explicit)
  • Classes with constructors where all parameters have default values
  • Records with primary constructors

Types that skip ordinal serialization:

  • Classes requiring constructor parameters without defaults
  • Abstract classes
  • Types that depend on DI for instantiation
// This type WILL get ordinal serialization (parameterless constructor)
[Factory]
public partial class SimpleDto
{
    public string Name { get; set; } = "";

    [Create]
    public static SimpleDto Create(string name) => new() { Name = name };
}

// This type will NOT get ordinal serialization (requires DI)
[Factory]
public partial class DomainEntity
{
    private readonly IEntityServices _services;

    public DomainEntity(IEntityServices services)
    {
        _services = services;
    }

    [Create]
    public static DomainEntity Create([Service] IEntityServices services)
        => new DomainEntity(services);
}

Backward-Compatible Interface Methods

Added default implementations to IMakeRemoteDelegateRequest for methods without CancellationToken, ensuring backward compatibility with existing implementations:

public interface IMakeRemoteDelegateRequest
{
    // New signatures with CancellationToken
    Task<T> ForDelegate<T>(Type delegateType, object?[]? parameters, CancellationToken cancellationToken);
    Task<T?> ForDelegateNullable<T>(Type delegateType, object?[]? parameters, CancellationToken cancellationToken);

    // Backward-compatible overloads (new in 0.5.0)
    Task<T> ForDelegate<T>(Type delegateType, object?[]? parameters)
        => ForDelegate<T>(delegateType, parameters, default);
    Task<T?> ForDelegateNullable<T>(Type delegateType, object?[]? parameters)
        => ForDelegateNullable<T>(delegateType, parameters, default);
}

IL Trimming Documentation

Added comprehensive IL Trimming documentation explaining:

  • How feature switch guards enable safe trimming
  • Configuration for Blazor WASM and other trimmed scenarios
  • How to verify trimming behavior

Note: This section originally documented ahead-of-time compilation compatibility. The documentation was later consolidated into the IL Trimming page, which covers the same reflection-free patterns.

Breaking Changes

None. This release is fully backward-compatible.

Bug Fixes

Fixed: Ordinal Serialization for Types Requiring Constructor Injection

Problem: RemoteFactory 0.2.0-0.4.0 generated ordinal serialization code using object initializer syntax (new Type { Prop = value }). This failed for types that require constructor parameters, such as:

// Neatoo pattern - constructor requires injected services
public partial class ContactPhone : EntityBase<ContactPhone>
{
    public ContactPhone(IEntityBaseServices<ContactPhone> services)
        : base(services) { }
}

The generated FromOrdinalArray method attempted:

// Generated code that failed to compile
return new ContactPhone { PhoneNumber = ... };  // ERROR: No parameterless constructor

Solution: The generator now detects types that require constructor parameters and skips ordinal serialization generation. These types fall back to named-property JSON serialization, which works correctly.

Impact:

  • Types requiring constructor DI: Use named serialization (slightly larger payloads)
  • Types with parameterless constructors: Continue using ordinal serialization (optimized)
  • No action required from users

Migration Guide

No migration required. Existing code works without changes:

  1. Types with parameterless constructors continue to use ordinal serialization
  2. Types requiring constructor DI automatically fall back to named serialization
  3. Remote operations work correctly in both cases

Serialization Behavior Summary

Type Pattern Ordinal Serialization Fallback
Parameterless constructor Yes N/A
All-default-params constructor Yes N/A
Record with primary constructor Yes N/A
Constructor with required params No Named serialization
Abstract class No Named serialization
Nested class No Named serialization

Commits

  • feat: Add constructor analysis to skip ordinal generation for DI-requiring types
  • feat: Add backward-compatible overloads to IMakeRemoteDelegateRequest
  • test: Add comprehensive constructor injection detection tests
  • docs: Add IL trimming documentation