| Severity | Error |
| Reported by | PostSharp |
| Message | Advice "<Advice>" is not valid on the instance constructor of type "<Type>": applying OnMethodEntryAdvice, OnMethodSuccessAdvice, OnMethodExitAdvice or OnMethodExceptionAdvice to an instance constructor of another assembly is not supported. Restrict the advice to methods. |
Cause
An aspect can enhance the declarations of a referenced assembly when you multicast it with the AttributeTargetAssemblies property. PostSharp does not modify the other assembly: it replaces the calls that the current assembly makes to the target method with calls to a generated method that runs the advices. PostSharp does not support this for constructors, and reports LA0181 when an OnMethodEntryAdvice, an OnMethodSuccessAdvice, an OnMethodExitAdvice or an OnMethodExceptionAdvice targets an instance constructor of another assembly.
This usually happens by default: the AttributeTargetElements of a MethodLevelAspect include the instance and static constructors, so an aspect multicast to a type of another assembly also reaches the constructors that the current assembly calls. An advice without pointcut has the targets of its aspect. <Advice> is an advice method of the group, and the message is reported at its location: the advice that has the pointcut of the group, or else the advice that sets a property of the group, or else the first advice of the group. <Type> is the type that declares the constructor.
LA0179 is the same error for an OnMethodBoundaryAspect or an OnExceptionAspect.
In the following example, a shipping library defines RateTable:
namespace Errors.LA0181_Error.Shipping;
public class RateTable
{
private readonly decimal ratePerKg;
public RateTable( decimal ratePerKg )
{
this.ratePerKg = ratePerKg;
}
public decimal GetPrice( decimal weightKg ) => weightKg * this.ratePerKg;
}
The application multicasts a [Log] aspect, whose OnEntry advice has no pointcut, to RateTable, whose constructor it calls:
// @SkipPostSharpOnDependency
using System;
using Errors.LA0181_Error.Shipping;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Extensibility;
using PostSharp.Serialization;
// The aspect is multicast to all methods of RateTable, including its constructor, which is in another assembly.
[assembly: Errors.LA0181_Error.Log(
AttributeTargetAssemblies = "LA0181_Error.Dependency",
AttributeTargetTypes = "Errors.LA0181_Error.Shipping.RateTable" )]
namespace Errors.LA0181_Error;
[PSerializable]
public class LogAttribute : MethodLevelAspect
{
[OnMethodEntryAdvice]
public void OnEntry( MethodExecutionArgs args )
{
Console.WriteLine( $"Calling {args.Method.DeclaringType!.Name}.{args.Method.Name}" );
}
}
public static class Program
{
public static void Main()
{
RateTable rates = new( 2.5m );
Console.WriteLine( $"Price: {rates.GetPrice( 4m ):0.00}" );
}
}
error LA0181: LA0181_Error.cs(21,17): Advice "Errors.LA0181_Error.LogAttribute.OnEntry(PostSharp.Aspects.MethodExecutionArgs)" is not valid on the instance constructor of type "Errors.LA0181_Error.Shipping.RateTable": applying OnMethodEntryAdvice, OnMethodSuccessAdvice, OnMethodExitAdvice or OnMethodExceptionAdvice to an instance constructor of another assembly is not supported. Restrict the advice to methods.
Resolution
- Restrict the aspect to methods: set AttributeTargetElements to Method.
- When the advice selects its targets with another pointcut, such as a MethodPointcut, exclude the constructors from the pointcut.
- When you own the library, apply the aspect in the library itself, where PostSharp can enhance the constructor.
In the following example, the aspect is applied to RateTable.GetPrice only.
// @SkipPostSharpOnDependency
using System;
using Errors.LA0181_Fixed.Shipping;
using PostSharp.Aspects;
using PostSharp.Aspects.Advices;
using PostSharp.Extensibility;
using PostSharp.Serialization;
// The aspect is multicast to the methods of RateTable only, not to its constructor.
[assembly: Errors.LA0181_Fixed.Log(
AttributeTargetAssemblies = "LA0181_Fixed.Dependency",
AttributeTargetTypes = "Errors.LA0181_Fixed.Shipping.RateTable",
AttributeTargetElements = MulticastTargets.Method )]
namespace Errors.LA0181_Fixed;
[PSerializable]
public class LogAttribute : MethodLevelAspect
{
[OnMethodEntryAdvice]
public void OnEntry( MethodExecutionArgs args )
{
Console.WriteLine( $"Calling {args.Method.DeclaringType!.Name}.{args.Method.Name}" );
}
}
public static class Program
{
public static void Main()
{
RateTable rates = new( 2.5m );
Console.WriteLine( $"Price: {rates.GetPrice( 4m ):0.00}" );
}
}
Calling RateTable.GetPrice
Price: 10.00
See Also
Reference
OnMethodEntryAdvice
MethodLevelAspect
AttributeTargetAssemblies
AttributeTargetElements
Other Resources