Open sandboxFocusImprove this doc

COM001: Field or Property Has Several Relationship Attributes

Severity Error
Reported by PostSharp.Patterns.Common
Message <Member> cannot have more than one custom attribute of type [Child], [Reference] or [Parent].

Cause

The AggregatableAttribute aspect builds the parent/child graph of your objects from the relationship attribute of each field and automatic property of the class: ChildAttribute when the object belongs to the instance, ReferenceAttribute when it is only referred to, and ParentAttribute when it is the parent of the instance. These relationships exclude each other, so PostSharp reports COM001 when a field or an automatic property has more than one of them.

When the PostSharpUnifiedAutomaticPropertyAnnotations MSBuild property is True, PostSharp reads the attributes of an automatic property and of its backing field ([field: Child]) as one set, so a different attribute on each of them also reports COM001.

In the following example, the Customer property of Invoice is marked both as a child and as a reference.

using System;
using PostSharp;
using PostSharp.Patterns.Model;

namespace Errors.COM001_Error;

[Aggregatable]
public class Customer
{
    public string Name { get; set; } = "Alice";
}

[Aggregatable]
public class Invoice
{
    // The property is marked both as a child and as a reference.
    [Child]
    [Reference]
    public Customer? Customer { get; set; }
}

public static class Program
{
    public static void Main()
    {
        Customer customer = new Customer();
        Invoice invoice = new Invoice { Customer = customer };

        object? parent = Post.Cast<Customer, IAggregatable>( customer ).Parent;
        Console.WriteLine( $"Customer: {invoice.Customer!.Name}, parent: {parent ?? "none"}" );
    }
}
error COM001: COM001_Error.cs(19,22): Errors.COM001_Error.Invoice.Customer cannot have more than one custom attribute of type [Child], [Reference] or [Parent].

Resolution

Keep the one attribute that describes the relationship:

  • ChildAttribute when the instance owns the object, which then gets the instance as its parent.
  • ReferenceAttribute when the object belongs to another part of the graph or is shared.
  • ParentAttribute when the field or property receives the parent of the instance.

In the following example, the invoice only refers to the customer, so the customer has no parent.

using System;
using PostSharp;
using PostSharp.Patterns.Model;

namespace Errors.COM001_Fixed;

[Aggregatable]
public class Customer
{
    public string Name { get; set; } = "Alice";
}

[Aggregatable]
public class Invoice
{
    // The invoice refers to the customer but does not own it, so the property is only a reference.
    [Reference]
    public Customer? Customer { get; set; }
}

public static class Program
{
    public static void Main()
    {
        Customer customer = new Customer();
        Invoice invoice = new Invoice { Customer = customer };

        object? parent = Post.Cast<Customer, IAggregatable>( customer ).Parent;
        Console.WriteLine( $"Customer: {invoice.Customer!.Name}, parent: {parent ?? "none"}" );
    }
}
Customer: Alice, parent: none

See Also

Reference

AggregatableAttribute
ChildAttribute
ReferenceAttribute
ParentAttribute

Other Resources

Annotating an Object Model for Parent/Child Relationships (Aggregatable)