How do I target attributes for a record class?
Asked Answered
K

2

55

When defining a record class, how do I target the attributes to the parameter, field or property?

For instance, I would like to use JsonIgnore but this doesn't compile as it has an attribute usage restriction to the field or property:

record Person(string FirstName, string LastName, [JsonIgnore] int Age);
Kynewulf answered 7/9, 2020 at 13:10 Comment(3)
@HimBromBeere yes it does. Records define properties in a constructor lineKynewulf
You could also reproduce your issue with a class instead of a record.Revolutionary
@HimBromBeere sure, but this question is going to come up as more people adopt record classes for DTOs. In the case of the class, you have the property explicitly defined where with records it’s combined with a constructor parameterKynewulf
K
100

To target the various parts of the expanded class, use the appropriate attribute target. For instance:

// Target the property, use `property`
record Person(string FirstName, string LastName, [property: JsonIgnore] int Age);

// Target the backing field of the property, use `field`
record Person(string FirstName, string LastName, [field: JsonIgnore] int Age);

// Target the constructor parameter, use `param`
record Person(string FirstName, string LastName, [param: SomeParamAttribute] int Age);
Kynewulf answered 7/9, 2020 at 13:10 Comment(3)
Daniel, do you know the reason why we have to specify the property target, even though int Age becomes a property in the resulting record?Harness
@Harness it’s ambiguous. Certain attributes only work on properties and otherwise it would fail at compile timeKynewulf
I noticed that if fails at compile time, but it looks to me that it would make sense for the compiler to assume that an unspecified target by default means property when using the positional syntax of records, since it is intended for the purpose of generating properties. In this specific case, JsonIgnore actually has multiple targets, but the compiler error also happens when an attribute is targeted only at properties. In any rate, thank you for sharing your thoughts! :]Harness
T
8

A real-life example:

This record

public record GetAccountHolderParameters([property: JsonProperty("accountHolderCode")] string Code, [property: JsonProperty("showDetails")] bool ShowDetails);

or this preferred syntax which is better to read

public record GetAccountHolderParameters(
    [property: JsonProperty("accountHolderCode")] string Code,
    [property: JsonProperty("showDetails")] bool ShowDetails
);

is equivalent to

public class GetAccountHolderParameters
{
    [JsonProperty(PropertyName = "accountHolderCode")]
    public string Code { get; set; }

    [JsonProperty(PropertyName = "showDetails")]
    public bool ShowDetails { get; set; }
}

Note about ASP.NET Core request parameters

You can't apply validation attributes [property: ... ] to your request parameters, see this question.

You will receive InvalidOperationException(...).

For details, see this issue.

Trentontrepan answered 30/7, 2022 at 4:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.