| Severity | Warning |
| Reported by | PostSharp |
| Message | Cannot apply the aspect "<Aspect>" to field "<Field>" because it is const. |
Cause
A LocationInterceptionAspect intercepts the reads and writes of a field or a property. The compiler replaces every use of a const field with its value, so the program never reads the field, and there is nothing to intercept. PostSharp reports the LA0116 warning and does not apply the aspect to the field. The rest of the program is woven normally.
Attribute multicasting skips constants, because LocationInterceptionAspect accepts non-literal fields only. The message comes from an IAspectProvider that provides the aspect to every field of a type, constants included. It points to the declaration where the providing aspect is applied.
In the following example, the [TraceFields] aspect provider adds the [TraceAccess] aspect to every field of OrderLine, including the MaxQuantity constant. The read of Quantity is traced, the read of MaxQuantity is not.
using System;
using System.Collections.Generic;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.LA0116_Error;
[PSerializable]
public class TraceAccessAttribute : LocationInterceptionAspect
{
public override void OnGetValue( LocationInterceptionArgs args )
{
Console.WriteLine( $"Reading {args.LocationName}." );
args.ProceedGetValue();
}
}
// Traces the access to every field of the target class.
[PSerializable]
public class TraceFieldsAttribute : TypeLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
{
Type type = (Type) targetElement;
// The aspect provider also adds the interception aspect to the constant MaxQuantity.
foreach ( FieldInfo field in type.GetFields( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly ) )
{
yield return new AspectInstance( field, new TraceAccessAttribute() );
}
}
}
[TraceFields]
public class OrderLine
{
public const int MaxQuantity = 100;
public int Quantity = 5;
}
public static class Program
{
public static void Main()
{
OrderLine line = new();
Console.WriteLine( $"{line.Quantity} of at most {OrderLine.MaxQuantity}." );
}
}
warning LA0116: LA0116_Error.cs(36,14): Cannot apply the aspect "Errors.LA0116_Error.TraceAccessAttribute" to field "Errors.LA0116_Error.OrderLine.MaxQuantity" because it is const.
Reading Quantity.
5 of at most 100.
Resolution
Skip the constants in the ProvideAspects method of the aspect provider: test the IsLiteral property of each field. If the value of the constant must be intercepted, make it a static readonly field or a property.
In the following example, the aspect provider skips MaxQuantity, and the build no longer reports the warning.
using System;
using System.Collections.Generic;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.LA0116_Fixed;
[PSerializable]
public class TraceAccessAttribute : LocationInterceptionAspect
{
public override void OnGetValue( LocationInterceptionArgs args )
{
Console.WriteLine( $"Reading {args.LocationName}." );
args.ProceedGetValue();
}
}
// Traces the access to every field of the target class.
[PSerializable]
public class TraceFieldsAttribute : TypeLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
{
Type type = (Type) targetElement;
foreach ( FieldInfo field in type.GetFields( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly ) )
{
// The aspect provider skips the constants, which have no storage to intercept.
if ( field.IsLiteral )
{
continue;
}
yield return new AspectInstance( field, new TraceAccessAttribute() );
}
}
}
[TraceFields]
public class OrderLine
{
public const int MaxQuantity = 100;
public int Quantity = 5;
}
public static class Program
{
public static void Main()
{
OrderLine line = new();
Console.WriteLine( $"{line.Quantity} of at most {OrderLine.MaxQuantity}." );
}
}
Reading Quantity.
5 of at most 100.
See Also
Reference
LocationInterceptionAspect
IAspectProvider
Other Resources
Intercepting Properties and Fields
Adding Aspects Programmatically Using IAspectProvider