| Severity | Error |
| Reported by | PostSharp |
| Message | Cannot apply the aspect "<Aspect>" to the static constructor of type "<Type>": a method interception aspect cannot be applied to a static constructor. |
Cause
A MethodInterceptionAspect replaces the body of its target method with a call to OnInvoke. PostSharp does not support this transformation on a static constructor, which the runtime calls itself, and reports LA0114 instead of weaving the aspect.
Attribute multicasting never applies a MethodInterceptionAspect to a static constructor, because the aspect does not accept this kind of target. The message comes from code that chooses the targets itself: an IAspectProvider that provides the aspect to the type initializer, or an OnMethodInvokeAdvice whose pointcut selects a static constructor.
<Type> is the type that declares the static constructor. The message points to the declaration where the providing aspect is applied.
In the following example, the [LogStaticMembers] aspect provider adds the [Log] interception aspect to the static methods of Settings, and also to its static constructor.
using System;
using System.Collections.Generic;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.LA0114_Error;
[PSerializable]
public class LogAttribute : MethodInterceptionAspect
{
public override void OnInvoke( MethodInterceptionArgs args )
{
Console.WriteLine( $"Calling {args.Method.Name}." );
args.Proceed();
}
}
// Logs the static methods of the target class.
[PSerializable]
public class LogStaticMembersAttribute : TypeLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
{
Type type = (Type) targetElement;
foreach ( MethodInfo method in type.GetMethods( BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly ) )
{
yield return new AspectInstance( method, new LogAttribute() );
}
// The aspect provider also adds the interception aspect to the static constructor.
if ( type.TypeInitializer != null )
{
yield return new AspectInstance( type.TypeInitializer, new LogAttribute() );
}
}
}
[LogStaticMembers]
public static class Settings
{
private static readonly Dictionary<string, string> _values;
static Settings()
{
_values = new Dictionary<string, string> { ["Currency"] = "EUR" };
}
public static string Get( string name ) => _values[name];
}
public static class Program
{
public static void Main()
{
Console.WriteLine( Settings.Get( "Currency" ) );
}
}
error LA0114: LA0114_Error.cs(41,21): Cannot apply the aspect "Errors.LA0114_Error.LogAttribute" to the static constructor of type "Errors.LA0114_Error.Settings": a method interception aspect cannot be applied to a static constructor.
Resolution
Provide the aspect to methods only: in the ProvideAspects method of the aspect provider, skip the type initializer and the other constructors. To run code when a type is initialized, call it from the static constructor itself.
In the following example, the aspect provider no longer adds the aspect to the static constructor.
using System;
using System.Collections.Generic;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace Errors.LA0114_Fixed;
[PSerializable]
public class LogAttribute : MethodInterceptionAspect
{
public override void OnInvoke( MethodInterceptionArgs args )
{
Console.WriteLine( $"Calling {args.Method.Name}." );
args.Proceed();
}
}
// Logs the static methods of the target class.
[PSerializable]
public class LogStaticMembersAttribute : TypeLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
{
Type type = (Type) targetElement;
// The aspect provider adds the interception aspect to methods only.
foreach ( MethodInfo method in type.GetMethods( BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly ) )
{
yield return new AspectInstance( method, new LogAttribute() );
}
}
}
[LogStaticMembers]
public static class Settings
{
private static readonly Dictionary<string, string> _values;
static Settings()
{
_values = new Dictionary<string, string> { ["Currency"] = "EUR" };
}
public static string Get( string name ) => _values[name];
}
public static class Program
{
public static void Main()
{
Console.WriteLine( Settings.Get( "Currency" ) );
}
}
Calling Get.
EUR
See Also
Reference
MethodInterceptionAspect
IAspectProvider
AspectInstance
Other Resources
Intercepting Methods
Adding Aspects Programmatically Using IAspectProvider