是否清除OnMethodBoundaryAspect和ILocationValidationAspect之间的方面冲突警



PostSharp 6.7.12版,用于工具和库。我定义了一些自定义属性:

[PSerializable]
public sealed class CheckInvariantAttribute : OnMethodBoundaryAspect
{
// Snip - build-time logic here...
public override void OnExit(MethodExecutionArgs args)
{
// Check stuff...
}
}
[Serializable]
public sealed class NotDefaultAttribute : LocationContractAttribute,
ILocationValidationAspect<Guid>,
ILocationValidationAspect<DateTime>,
IValidableAnnotation
{
// Snip - build-time logic here...
public Exception ValidateValue(
DateTime value, 
string locationName, 
LocationKind locationKind, 
LocationValidationContext contect)
{
// Snip, do stuff...
}
public Exception ValidateValue(
Guid value, 
string locationName, 
LocationKind locationKind, 
LocationValidationContext contect)
{
// Snip, do stuff...
}
}

我也在使用其他可用的代码契约属性。我将这两种方法应用于同一种方法:

[CheckInvariant]
public virtual void DoSomething(
[NotNull] SomeObjectType inst,
[NotDefault] DateTime someVal,
[StrictlyPositive] Decimal someAmt)
{
// Snip, do stuff...
}

当我这样做时,我会得到一个编译时警告,状态为Conflicting aspects on "My.Namespace.MyClass.DoSomething( /* insert parameters here */ )": transformations "My.Namespace.NotDefaultAttribute: Validates the value passed to parameter 'someVal' and "My.Namespace.CheckInvariantAttribute: Wrapped by advice(s) OnExit" are not commutative, but they are not strongly ordered. Their order of execution is undeterministic.

首先,我希望这些应该是确定性的——一个将方面应用于参数,而另一个在方法退出时应用。这里有一个自然的秩序。除此之外,我试着将它们标记为"通勤",我试过按角色或优先级排序,但在所有情况下都失败了。(我可能做得不对。(

我该如何摆脱这些警告?

以下是这个示例位置的构建输出:

1>C:MyProjectSomeClass.cs(159,23,159,27): warning PS0114: Conflicting aspects on "My.Namespace.MyClass.DoSomething(SometObjectType, System.DateTime, System.Decimal)": transformations "My.Namespace.NotDefaultAttribute: Validates the value passed to parameter 'someVal'" and "My.Namespace.CheckInvariantAttribute: Wrapped by advice(s) OnExit" are not commutative, but they are not strongly ordered. Their order of execution is undeterministic.
1>NamespaceMyClass.cs(159,23,159,27): message PS0124: Detail of dependencies for the previous warnings: 
1>NamespaceMyClass.cs(159,23,159,27): message PS0124: My.Namespace.CheckInvariantAttribute: Marker BEFORE (54):
1>NamespaceMyClass.cs(159,23,159,27): message PS0124:    (no dependency)
1>NamespaceMyClass.cs(159,23,159,27): message PS0124: PostSharp.Patterns.Contracts.NotNullAttribute: Validates the value passed to parameter 'inst':
1>NamespaceMyClass.cs(159,23,159,27): message PS0124:    Provide Role=Validation
1>NamespaceMyClass.cs(159,23,159,27): message PS0124: My.Namespace.NotDefaultAttribute: Validates the value passed to parameter 'someVal':
1>NamespaceMyClass.cs(159,23,159,27): message PS0124:    Provide Role=Validation
1>NamespaceMyClass.cs(159,23,159,27): message PS0124: My.Namespace.CheckInvariantAttribute: Wrapped by advice(s) OnExit:
1>NamespaceMyClass.cs(159,23,159,27): message PS0124:    Action=Order, Position=After, Condition={equals "My.Namespace.CheckInvariantAttribute: Marker BEFORE (54)"}
1>NamespaceMyClass.cs(159,23,159,27): message PS0124:    Action=Order, Position=Before, Condition={equals "My.Namespace.CheckInvariantAttribute: Marker AFTER (54)"}
1>NamespaceMyClass.cs(159,23,159,27): message PS0124: PostSharp.Patterns.Contracts.StrictlyPositiveAttribute: Validates the value passed to parameter 'someAmt':
1>NamespaceMyClass.cs(159,23,159,27): message PS0124:    Provide Role=Validation
1>NamespaceMyClass.cs(159,23,159,27): message PS0124: My.Namespace.CheckInvariantAttribute: Marker AFTER (54):
1>NamespaceMyClass.cs(159,23,159,27): message PS0124:    (no dependency)
属性[NotDefault]应用于参数时,实际转换应用于方法体。它基本上与[CheckInvariant]方面的OnMethodBoundary变换相同。您可以想象转换后的方法体具有以下结构:
NotDefaultOnEntry
try
{
CheckInvariantOnEntry
try
{
// original method body
CheckInvariantOnSuccess
}
catch
{
CheckInvariantOnException
}
finally
{
CheckInvariantOnExit
}
NotDefaultOnSuccess
}
catch
{
NotDefaultOnException
}
finally
{
NotDefaultOnExit
}

正如您所看到的,方面的顺序将影响方法体包装的应用顺序。当然,在您的特定情况下,这些方面并没有提供所有可能的建议,最终的方法主体结构更简单。PostSharp在这种情况下仍然必须发出警告,以避免意外和意外行为。

可以使用方面角色依赖项对这些方面进行排序。对NotDefaultAttribute应用[ProvideAspectRole],对CheckInvariantAttribute应用[AspectRoleDependency],如下所示。

[Serializable]
[ProvideAspectRole(StandardRoles.Validation)]
public sealed class NotDefaultAttribute : LocationContractAttribute,
ILocationValidationAspect<Guid>,
ILocationValidationAspect<DateTime>,
IValidableAnnotation
{
// ...
}
[PSerializable]
[AspectRoleDependency(AspectDependencyAction.Order, AspectDependencyPosition.After, StandardRoles.Validation)]
public sealed class CheckInvariantAttribute : OnMethodBoundaryAspect
{
// ...
}

最新更新