| Severity | Error |
| Reported by | PostSharp.Patterns.Aggregation |
| Message | The field or property "<Member>" cannot be read-only because it is a [Child] of a struct type. Remove the readonly modifier of the field, or add a setter to the automatic property. |
Cause
A child of an AggregatableAttribute class can be a struct when the struct implements IAttachable. When PostSharp attaches the child to its parent, it calls AttachToParent, which stores the parent in the struct. A struct is a value, so attaching it changes the struct stored in the field, which a read-only field does not allow. PostSharp therefore reports COM009 when a field marked with ChildAttribute has a struct type and is readonly, or when such an automatic property has only a getter, whose backing field is read-only.
In the following example, the getter-only Size property of Order is a child of the struct type Dimensions.
using System;
using PostSharp.Patterns.Model;
namespace Errors.COM009_Error;
[Aggregatable]
public class Order
{
// The backing field of a getter-only property is read-only.
[Child]
public Dimensions Size { get; } = new Dimensions( 30, 20 );
}
// A struct can be a child only when it implements IAttachable.
public struct Dimensions : IAttachable
{
public Dimensions( int width, int height )
{
this.Width = width;
this.Height = height;
this.Parent = null;
}
public int Width { get; }
public int Height { get; }
public object? Parent { get; private set; }
public RelationshipKind ParentRelationship => this.Parent == null ? RelationshipKind.None : RelationshipKind.Child;
public event EventHandler? ParentChanged
{
add { }
remove { }
}
public event EventHandler<AncestorChangedEventArgs>? AncestorChanged
{
add { }
remove { }
}
public bool VisitChildren( ChildVisitor visitor, ChildVisitorOptions options = ChildVisitorOptions.None, object? state = null ) => true;
public bool AttachToParent( RelationshipInfo relationshipInfo, IAttacher attacher, object attacherState )
{
this.Parent = attacher.GetNode( attacherState );
return true;
}
public bool DetachFromParent()
{
this.Parent = null;
return true;
}
public void OnDeserialization( object caller )
{
}
}
public static class Program
{
public static void Main()
{
var order = new Order();
Console.WriteLine( $"The size is attached to the order: {order.Size.Parent == order}" );
}
}
error COM009: COM009_Error.cs(11,23): The field or property "Errors.COM009_Error.Order.Size" cannot be read-only because it is a [Child] of a struct type. Remove the readonly modifier of the field, or add a setter to the automatic property.
Resolution
- For an automatic property, add a setter, which can be
private. - For a field, remove the
readonlymodifier.
In the following example, Size has a private setter, so the struct is attached to the order.
using System;
using PostSharp.Patterns.Model;
namespace Errors.COM009_Fixed;
[Aggregatable]
public class Order
{
// With a setter, the backing field is not read-only.
[Child]
public Dimensions Size { get; private set; } = new Dimensions( 30, 20 );
}
// A struct can be a child only when it implements IAttachable.
public struct Dimensions : IAttachable
{
public Dimensions( int width, int height )
{
this.Width = width;
this.Height = height;
this.Parent = null;
}
public int Width { get; }
public int Height { get; }
public object? Parent { get; private set; }
public RelationshipKind ParentRelationship => this.Parent == null ? RelationshipKind.None : RelationshipKind.Child;
public event EventHandler? ParentChanged
{
add { }
remove { }
}
public event EventHandler<AncestorChangedEventArgs>? AncestorChanged
{
add { }
remove { }
}
public bool VisitChildren( ChildVisitor visitor, ChildVisitorOptions options = ChildVisitorOptions.None, object? state = null ) => true;
public bool AttachToParent( RelationshipInfo relationshipInfo, IAttacher attacher, object attacherState )
{
this.Parent = attacher.GetNode( attacherState );
return true;
}
public bool DetachFromParent()
{
this.Parent = null;
return true;
}
public void OnDeserialization( object caller )
{
}
}
public static class Program
{
public static void Main()
{
var order = new Order();
Console.WriteLine( $"The size is attached to the order: {order.Size.Parent == order}" );
}
}
The size is attached to the order: True
See Also
Reference
AggregatableAttribute
ChildAttribute
IAttachable
Other Resources
Annotating an Object Model for Parent/Child Relationships (Aggregatable)