| Severity | Error |
| Reported by | PostSharp |
| Message | Conflicting aspects on "<Declaration>": according to aspect dependencies, transformation "<Transformation1>" should be located both before and after transformation "<Transformation2>". |
Cause
An aspect class can have several dependencies, for example an AspectRoleDependencyAttribute for a role and an AspectTypeDependencyAttribute for an aspect type. When PostSharp compares two transformations on the same declaration, it looks for the dependencies of the first one, with the Order or Require action and a position, that match the second one. It reports PS0115 when two of these dependencies give opposite positions, Before and After.
This usually happens when the other aspect matches two dependencies in different ways: by its type and by a role that it provides, or by a role and by an effect. PostSharp follows the error with an informational message that lists the dependencies of both transformations.
In the following example, TraceAttribute runs before the caching role, but after CacheAttribute, which provides this role.
using System;
using PostSharp.Aspects;
using PostSharp.Aspects.Dependencies;
using PostSharp.Serialization;
namespace Errors.PS0115_Error;
[PSerializable]
[ProvideAspectRole( StandardRoles.Caching )]
public class CacheAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args ) => Console.WriteLine( "Look up the cache" );
}
[PSerializable]
[ProvideAspectRole( StandardRoles.Tracing )]
[AspectRoleDependency( AspectDependencyAction.Order, AspectDependencyPosition.Before, StandardRoles.Caching )]
[AspectTypeDependency( AspectDependencyAction.Order, AspectDependencyPosition.After, typeof(CacheAttribute) )] // Contradicts the dependency above: CacheAttribute provides the Caching role.
public class TraceAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args ) => Console.WriteLine( "Trace" );
}
public class ProductCatalog
{
[Cache]
[Trace]
public string GetProductName( int id )
{
return id == 1 ? "Coffee" : "Tea";
}
}
public static class Program
{
public static void Main()
{
Console.WriteLine( new ProductCatalog().GetProductName( 1 ) );
}
}
error PS0115: PS0115_Error.cs(28,19): Conflicting aspects on "Errors.PS0115_Error.ProductCatalog.GetProductName(System.Int32)": according to aspect dependencies, transformation "Errors.PS0115_Error.TraceAttribute: Marker AFTER (3)" should be located both before and after transformation "Errors.PS0115_Error.CacheAttribute: Marker AFTER (2)".
Resolution
Keep the dependency that describes the order you want, and remove or reverse the other one. When the second aspect matches both dependencies by accident, for example because it provides a role that you did not expect, make one of the dependencies more specific.
In the following example, only the role dependency remains, and TraceAttribute runs before CacheAttribute.
using System;
using PostSharp.Aspects;
using PostSharp.Aspects.Dependencies;
using PostSharp.Serialization;
namespace Errors.PS0115_Fixed;
[PSerializable]
[ProvideAspectRole( StandardRoles.Caching )]
public class CacheAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args ) => Console.WriteLine( "Look up the cache" );
}
[PSerializable]
[ProvideAspectRole( StandardRoles.Tracing )]
[AspectRoleDependency( AspectDependencyAction.Order, AspectDependencyPosition.Before, StandardRoles.Caching )] // The only dependency that orders the two aspects.
public class TraceAttribute : OnMethodBoundaryAspect
{
public override void OnEntry( MethodExecutionArgs args ) => Console.WriteLine( "Trace" );
}
public class ProductCatalog
{
[Cache]
[Trace]
public string GetProductName( int id )
{
return id == 1 ? "Coffee" : "Tea";
}
}
public static class Program
{
public static void Main()
{
Console.WriteLine( new ProductCatalog().GetProductName( 1 ) );
}
}
Trace
Look up the cache
Coffee
See Also
Reference
AspectRoleDependencyAttribute
AspectTypeDependencyAttribute
AspectDependencyPosition
Other Resources