MapWhen Attribute
November 22, 2025 ยท View on GitHub
The [MapWhen] attribute enables conditional property mapping based on source property values. Properties are only mapped when the specified condition evaluates to true.
Basic Usage
[Facet(typeof(Order))]
public partial class OrderDto
{
[MapWhen("Status == OrderStatus.Completed")]
public DateTime? CompletedAt { get; set; }
}
When Status is Completed, CompletedAt is mapped from source. Otherwise, it defaults to null.
Supported Conditions
Boolean Properties
[MapWhen("IsActive")]
public string? Email { get; set; }
Equality Comparisons
[MapWhen("Status == OrderStatus.Completed")]
public DateTime? CompletedAt { get; set; }
[MapWhen("Status != OrderStatus.Cancelled")]
public string? TrackingNumber { get; set; }
Null Checks
[MapWhen("Email != null")]
public string? Email { get; set; }
Numeric Comparisons
[MapWhen("Age >= 18")]
public string? AdultContent { get; set; }
Negation
[MapWhen("!IsDeleted")]
public string? Content { get; set; }
Multiple Conditions
Multiple [MapWhen] attributes on the same property are combined with AND logic:
[MapWhen("IsActive")]
[MapWhen("Status == OrderStatus.Completed")]
public DateTime? CompletedAt { get; set; }
This maps CompletedAt only when IsActive is true AND Status is Completed.
Generated Code
Constructor
// Input
[Facet(typeof(Order))]
public partial class OrderDto
{
[MapWhen("Status == OrderStatus.Completed")]
public DateTime? CompletedAt { get; set; }
}
// Generated constructor
public OrderDto(Order source)
{
Id = source.Id;
Status = source.Status;
CompletedAt = (source.Status == OrderStatus.Completed)
? source.CompletedAt
: default;
}
Projection
The same conditional logic is applied in the Projection expression for use with Entity Framework Core:
public static Expression<Func<Order, OrderDto>> Projection => source => new OrderDto
{
Id = source.Id,
Status = source.Status,
CompletedAt = (source.Status == OrderStatus.Completed)
? source.CompletedAt
: default
};
Attribute Properties
| Property | Type | Description |
|---|---|---|
Condition | string | The condition expression (required) |
Default | object? | Custom default value when condition is false |
IncludeInProjection | bool | Whether to include in Projection expression (default: true) |
Custom Default Values
[MapWhen("HasPrice", Default = 0)]
public decimal Price { get; set; }
Excluding from Projection
For conditions that can't be translated to SQL:
[MapWhen("IsActive", IncludeInProjection = false)]
public string? Email { get; set; }
Expression Syntax
The condition string uses C# expression syntax:
Supported Operators
- Comparison:
==,!=,<,>,<=,>= - Logical:
&&,||,!
Property Access
- Simple:
IsActive,Status,Email - Enum values:
OrderStatus.Completed,Status == OrderStatus.Pending
Literals
- Booleans:
true,false - Null:
null - Numbers:
18,0
Example Use Cases
Status-Dependent Fields
[Facet(typeof(Subscription))]
public partial class SubscriptionDto
{
public SubscriptionStatus Status { get; set; }
[MapWhen("Status == SubscriptionStatus.Active")]
public DateTime? NextBillingDate { get; set; }
[MapWhen("Status == SubscriptionStatus.Cancelled")]
public string? CancellationReason { get; set; }
}
Conditional Sensitive Data
[Facet(typeof(Employee))]
public partial class EmployeeDto
{
public string Name { get; set; }
[MapWhen("!IsSalaryConfidential")]
public decimal? Salary { get; set; }
}
Age-Gated Content
[Facet(typeof(User))]
public partial class UserDto
{
public int Age { get; set; }
[MapWhen("Age >= 18")]
public string? AdultPreferences { get; set; }
}
Limitations
- Method calls in conditions (like
string.IsNullOrEmpty()) are not supported - Nested property access (like
Address.City) is not supported - Complex expressions may need to be simplified
Best Practices
- Keep conditions simple - Use basic comparisons and boolean checks
- Use nullable properties - Since conditions may be false, properties should typically be nullable
- Consider EF Core translation - If using projections with a database, ensure conditions can translate to SQL
- Test both paths - Write tests for both when conditions are true and false