| Severity | Error |
| Reported by | PostSharp |
| Message | Aspect "<Aspect>" cannot be applied to property "<Property>" because it is read-only. |
Cause
An aspect that implements ILocationValidationAspect<T>, such as a contract, validates the values that are assigned to a field, a property or a parameter. For a property, PostSharp inserts the validation into the setter. When the property has no setter, for example a property with an expression body that only returns a field, there is no assignment to validate, so PostSharp reports LA0136.
In the following example, the [Positive] aspect is applied to the Quantity property, which only has a getter.
using System;
using PostSharp.Aspects;
using PostSharp.Reflection;
using PostSharp.Serialization;
namespace Errors.LA0136_Error;
[PSerializable]
public class PositiveAttribute : LocationLevelAspect, ILocationValidationAspect<int>
{
public Exception? ValidateValue( int value, string locationName, LocationKind locationKind, LocationValidationContext context )
=> value <= 0 ? new ArgumentOutOfRangeException( locationName, $"{locationName} must be positive." ) : null;
}
public class OrderLine
{
private int quantity;
public OrderLine( int quantity )
{
this.quantity = quantity;
}
// The property has no setter, so no value is ever assigned to it.
[Positive]
public int Quantity => this.quantity;
}
public static class Program
{
public static void Main()
{
try
{
var line = new OrderLine( 0 );
Console.WriteLine( line.Quantity );
}
catch ( ArgumentOutOfRangeException e )
{
Console.WriteLine( e.Message );
}
}
}
error LA0136: LA0136_Error.cs(26,16): Aspect "Errors.LA0136_Error.PositiveAttribute" cannot be applied to property "Errors.LA0136_Error.OrderLine.Quantity" because it is read-only.
Resolution
- Give the property a setter, which can be private, and assign the value through the property.
- Otherwise, apply the aspect where the value is assigned: to the backing field, or to the parameter that receives the value.
In the following example, Quantity is an automatic property with a private setter, which the constructor assigns, so the aspect rejects the invalid quantity.
using System;
using PostSharp.Aspects;
using PostSharp.Reflection;
using PostSharp.Serialization;
namespace Errors.LA0136_Fixed;
[PSerializable]
public class PositiveAttribute : LocationLevelAspect, ILocationValidationAspect<int>
{
public Exception? ValidateValue( int value, string locationName, LocationKind locationKind, LocationValidationContext context )
=> value <= 0 ? new ArgumentOutOfRangeException( locationName, $"{locationName} must be positive." ) : null;
}
public class OrderLine
{
public OrderLine( int quantity )
{
this.Quantity = quantity;
}
// The property has a setter, which the aspect validates.
[Positive]
public int Quantity { get; private set; }
}
public static class Program
{
public static void Main()
{
try
{
var line = new OrderLine( 0 );
Console.WriteLine( line.Quantity );
}
catch ( ArgumentOutOfRangeException e )
{
Console.WriteLine( e.Message );
}
}
}
Quantity must be positive. (Parameter 'Quantity')
See Also
Reference
ILocationValidationAspect<T>
LocationLevelAspect
Other Resources