| Severity | Error |
| Reported by | PostSharp |
| Message | Cannot apply the aspect "<Aspect>" to "<Target>": instance-scoped aspects cannot be applied to value types or members of value types. |
Cause
An instance-scoped aspect, which implements IInstanceScopedAspect or derives from InstanceLevelAspect, has one instance per instance of its target type. PostSharp stores this instance in a field that it adds to the target type. PostSharp supports this for classes only, and reports LA0112 when the declaring type of the target is a value type: a struct, or a member of a struct.
In the following example, the instance-scoped [CountCalls] aspect is applied to a method of the Money struct.
using System;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.LA0112_Error;
[PSerializable]
public class CountCallsAttribute : OnMethodBoundaryAspect, IInstanceScopedAspect
{
private int count;
public object CreateInstance( AdviceArgs adviceArgs ) => this.MemberwiseClone();
public void RuntimeInitializeInstance()
{
}
public override void OnEntry( MethodExecutionArgs args )
{
this.count++;
Console.WriteLine( $"{args.Method.Name} called {this.count} time(s) on this instance." );
}
}
public struct Money
{
public decimal Amount { get; set; }
// The instance-scoped aspect is applied to a member of a struct.
[CountCalls]
public string Format() => $"{this.Amount:0.00} EUR";
}
public static class Program
{
public static void Main()
{
var price = new Money { Amount = 12.5m };
Console.WriteLine( price.Format() );
Console.WriteLine( price.Format() );
}
}
error LA0112: LA0112_Error.cs(31,19): Cannot apply the aspect "Errors.LA0112_Error.CountCallsAttribute" to "Errors.LA0112_Error.Money.Format": instance-scoped aspects cannot be applied to value types or members of value types.
Resolution
- Make the target type a class.
- Or make the aspect static-scoped: remove IInstanceScopedAspect, so that one instance of the aspect serves all the instances of the target type.
In the following example, Money is a class, and each instance counts its own calls.
using System;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.LA0112_Fixed;
[PSerializable]
public class CountCallsAttribute : OnMethodBoundaryAspect, IInstanceScopedAspect
{
private int count;
public object CreateInstance( AdviceArgs adviceArgs ) => this.MemberwiseClone();
public void RuntimeInitializeInstance()
{
}
public override void OnEntry( MethodExecutionArgs args )
{
this.count++;
Console.WriteLine( $"{args.Method.Name} called {this.count} time(s) on this instance." );
}
}
// Money is a class, so each instance can have its own instance of the aspect.
public class Money
{
public decimal Amount { get; set; }
[CountCalls]
public string Format() => $"{this.Amount:0.00} EUR";
}
public static class Program
{
public static void Main()
{
var price = new Money { Amount = 12.5m };
Console.WriteLine( price.Format() );
Console.WriteLine( price.Format() );
}
}
Format called 1 time(s) on this instance.
12.50 EUR
Format called 2 time(s) on this instance.
12.50 EUR
See Also
Reference
IInstanceScopedAspect
InstanceLevelAspect
Other Resources