Hooks

Facette generates partial method hooks that you can implement to run custom logic before or after mapping operations.

Available hooks

HookCalled
OnAfterFromSource(TSource source)After FromSource completes
OnBeforeToSource(TSource target)Before ToSource returns, with the target object
OnAfterToSource(TSource target)After ToSource populates the target, before returning

OnAfterFromSource

Runs after all properties have been mapped from the source. Use this to compute derived properties:

[Facette(typeof(Employee), "SocialSecurityNumber",
    NestedDtos = new[] { typeof(AddressDto) })]
public partial record EmployeeDto
{
    [FacetteIgnore]
    public string FullName { get; set; } = "";

    partial void OnAfterFromSource(Employee source)
    {
        FullName = $"{source.FirstName} {source.LastName}";
    }
}
var dto = EmployeeDto.FromSource(employee);
Console.WriteLine(dto.FullName); // "Alice Johnson"

OnBeforeToSource / OnAfterToSource

Run custom logic during ToSource():

[Facette(typeof(Employee), "SocialSecurityNumber")]
public partial record EmployeeDto
{
    partial void OnBeforeToSource(Employee target)
    {
        // Runs before properties are assigned to target
    }

    partial void OnAfterToSource(Employee target)
    {
        // Runs after all properties are assigned
        // Useful for setting computed or derived fields on the source
    }
}

How it works

Since hooks are declared as partial void methods, they compile to no-ops if you don't implement them — zero overhead when unused. The generator emits the partial method declarations, and you provide the implementations in your part of the partial record.

Tips

  • Use [FacetteIgnore] on properties that are populated by hooks, so the generator doesn't try to map them from the source
  • Hooks run synchronously and have access to both the DTO instance (this) and the source/target object
  • Hooks don't affect Projection — expression trees cannot contain imperative code