摆脱 OnMethodBoundaryAspect 和 ILocationValidationAspect 之间的方面冲突警告?
Get rid of aspect conflict warnings between OnMethodBoundaryAspect and 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:\MyProject\SomeClass.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>Namespace\MyClass.cs(159,23,159,27): message PS0124: Detail of dependencies for the previous warnings:
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: My.Namespace.CheckInvariantAttribute: Marker BEFORE (54):
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: (no dependency)
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: PostSharp.Patterns.Contracts.NotNullAttribute: Validates the value passed to parameter 'inst':
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: Provide Role=Validation
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: My.Namespace.NotDefaultAttribute: Validates the value passed to parameter 'someVal':
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: Provide Role=Validation
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: My.Namespace.CheckInvariantAttribute: Wrapped by advice(s) OnExit:
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: Action=Order, Position=After, Condition={equals "My.Namespace.CheckInvariantAttribute: Marker BEFORE (54)"}
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: Action=Order, Position=Before, Condition={equals "My.Namespace.CheckInvariantAttribute: Marker AFTER (54)"}
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: PostSharp.Patterns.Contracts.StrictlyPositiveAttribute: Validates the value passed to parameter 'someAmt':
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: Provide Role=Validation
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: My.Namespace.CheckInvariantAttribute: Marker AFTER (54):
1>Namespace\MyClass.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 仍然必须发出警告以避免意外和意外行为。
您可以使用方面角色依赖关系来对这些方面进行排序。将 [ProvideAspectRole]
应用到 NotDefaultAttribute
并将 [AspectRoleDependency]
应用到 CheckInvariantAttribute
,如下所示。
[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
{
// ...
}
用于工具和库的 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:\MyProject\SomeClass.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>Namespace\MyClass.cs(159,23,159,27): message PS0124: Detail of dependencies for the previous warnings:
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: My.Namespace.CheckInvariantAttribute: Marker BEFORE (54):
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: (no dependency)
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: PostSharp.Patterns.Contracts.NotNullAttribute: Validates the value passed to parameter 'inst':
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: Provide Role=Validation
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: My.Namespace.NotDefaultAttribute: Validates the value passed to parameter 'someVal':
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: Provide Role=Validation
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: My.Namespace.CheckInvariantAttribute: Wrapped by advice(s) OnExit:
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: Action=Order, Position=After, Condition={equals "My.Namespace.CheckInvariantAttribute: Marker BEFORE (54)"}
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: Action=Order, Position=Before, Condition={equals "My.Namespace.CheckInvariantAttribute: Marker AFTER (54)"}
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: PostSharp.Patterns.Contracts.StrictlyPositiveAttribute: Validates the value passed to parameter 'someAmt':
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: Provide Role=Validation
1>Namespace\MyClass.cs(159,23,159,27): message PS0124: My.Namespace.CheckInvariantAttribute: Marker AFTER (54):
1>Namespace\MyClass.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 仍然必须发出警告以避免意外和意外行为。
您可以使用方面角色依赖关系来对这些方面进行排序。将 [ProvideAspectRole]
应用到 NotDefaultAttribute
并将 [AspectRoleDependency]
应用到 CheckInvariantAttribute
,如下所示。
[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
{
// ...
}