| Severity | Error |
| Reported by | PostSharp.Patterns.Common |
| Message | Cannot apply the [<Attribute>] attribute to the "<Property>" property because it is not an automatic property. Apply it instead to the backing field. |
Cause
The AggregatableAttribute aspect tracks the parent/child relationships of an object through the fields that store them. On an automatic property, PostSharp finds the field that the compiler generates. On a property with its own get or set accessor, PostSharp cannot tell which field the property reads or writes, if any, so it reports COM003 when the property has a ChildAttribute, ReferenceAttribute or ParentAttribute attribute.
In the following example, the Address property of Customer checks its value in its set accessor, so it is not an automatic property.
using System;
using PostSharp;
using PostSharp.Patterns.Model;
namespace Errors.COM003_Error;
[Aggregatable]
public class Address
{
public string City { get; set; } = "Prague";
}
[Aggregatable]
public class Customer
{
private Address? address;
// The attribute is on a property that has its own accessors.
[Child]
public Address? Address
{
get => this.address;
set => this.address = value ?? throw new ArgumentNullException( nameof(value) );
}
}
public static class Program
{
public static void Main()
{
Customer customer = new Customer { Address = new Address() };
object? parent = Post.Cast<Address, IAggregatable>( customer.Address! ).Parent;
Console.WriteLine( $"City: {customer.Address!.City}, parent of the address: {parent?.GetType().Name ?? "none"}" );
}
}
error COM003: COM003_Error.cs(20,21): Cannot apply the [ChildAttribute] attribute to the "Errors.COM003_Error.Customer.Address" property because it is not an automatic property. Apply it instead to the backing field.
Resolution
Move the attribute from the property to the field that stores its value. Alternatively, when the property needs no logic in its accessors, make it an automatic property and keep the attribute on it.
In the following example, the attribute is on the address field, and the address gets the customer as its parent.
using System;
using PostSharp;
using PostSharp.Patterns.Model;
namespace Errors.COM003_Fixed;
[Aggregatable]
public class Address
{
public string City { get; set; } = "Prague";
}
[Aggregatable]
public class Customer
{
// The attribute is on the field that stores the value of the property.
[Child]
private Address? address;
public Address? Address
{
get => this.address;
set => this.address = value ?? throw new ArgumentNullException( nameof(value) );
}
}
public static class Program
{
public static void Main()
{
Customer customer = new Customer { Address = new Address() };
object? parent = Post.Cast<Address, IAggregatable>( customer.Address! ).Parent;
Console.WriteLine( $"City: {customer.Address!.City}, parent of the address: {parent?.GetType().Name ?? "none"}" );
}
}
City: Prague, parent of the address: Customer
See Also
Reference
AggregatableAttribute
ChildAttribute
ReferenceAttribute
ParentAttribute
Other Resources
Annotating an Object Model for Parent/Child Relationships (Aggregatable)