为什么我不能在最新版本的 PostSharp 中将 IInstanceScopedAspect 应用于静态 class?
Why can I not apply IInstanceScopedAspect to static class in last version of PostSharp?
我有这样一个方面:
[PSerializable]
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property | AttributeTargets.Event, AllowMultiple = false )]
public abstract class LogAttribute : OnMethodBoundaryAspect, IInstanceScopedAspect {
// CompileTime/Init
public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo) {
}
// CompileTime/Validate
public override bool CompileTimeValidate(MethodBase method) {
return true;
}
// Runtime/Init/Static
public override void RuntimeInitialize(MethodBase method) {
}
// Runtime/Init/Instance (Only if method is not static)
object IInstanceScopedAspect.CreateInstance(AdviceArgs args) {
var clone = (LogAttribute) MemberwiseClone();
return clone;
}
void IInstanceScopedAspect.RuntimeInitializeInstance() {
}
// Advices
public override void OnEntry(MethodExecutionArgs args) {
}
public override void OnSuccess(MethodExecutionArgs args) {
}
public override void OnException(MethodExecutionArgs args) {
}
public override void OnExit(MethodExecutionArgs args) {
}
public override void OnYield(MethodExecutionArgs args) {
}
public override void OnResume(MethodExecutionArgs args) {
}
}
我将它用于非静态和静态方法以及 类。但是现在我不能在静态类中使用IInstanceScopedAspect
!
我遇到错误:Error LA0203 Cannot apply instance-level aspect "LogAttribute" to static class "...".
改变了什么?我现在该怎么做?
这在 PostSharp 6.4 中是不允许的,因为可以以违反 C# 的静态 classes 定义(添加的实例成员等)的方式更改方面的目标 class。如果你需要 IInstanceScopedAspect
,现在正确的方法是有两个独立的方面,例如实例和静态方法。
实现此目标的最佳方法是拥有创建正确相位的 IAspectProvider
:
[PSerializable]
public class LogAttribute : MethodLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
if (targetElement is MethodBase method)
{
if (method.IsStatic)
yield return new AspectInstance(targetElement, new StaticLogAspect());
else
yield return new AspectInstance(targetElement, new InstanceLogAspect());
}
}
}
[PSerializable]
internal abstract class BaseLogAspect : IAspect
{
[OnMethodEntryAdvice]
[SelfPointcut]
public virtual void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine("Base");
}
}
[PSerializable]
internal class StaticLogAspect : BaseLogAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine("Static");
}
}
[PSerializable]
internal class InstanceLogAspect : BaseLogAspect, IInstanceScopedAspect
{
public object CreateInstance(AdviceArgs adviceArgs)
{
return new InstanceLogAspect();
}
public void RuntimeInitializeInstance()
{
}
public override void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine("Instance");
}
}
请注意,IInstanceScopedAspect
导致为每个目标实例分配一个方面对象 class。当您在方法上使用它时,此类方面可能会导致对象的内存占用量显着增加。
如果您的建议方法中需要与实例相关的信息,最好在类型上有一个 "central" 实例范围的方面。该方面存储实例信息并将接口引入目标class。然后方法级方面使用引入的接口来获取有关实例的信息。
我有这样一个方面:
[PSerializable]
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property | AttributeTargets.Event, AllowMultiple = false )]
public abstract class LogAttribute : OnMethodBoundaryAspect, IInstanceScopedAspect {
// CompileTime/Init
public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo) {
}
// CompileTime/Validate
public override bool CompileTimeValidate(MethodBase method) {
return true;
}
// Runtime/Init/Static
public override void RuntimeInitialize(MethodBase method) {
}
// Runtime/Init/Instance (Only if method is not static)
object IInstanceScopedAspect.CreateInstance(AdviceArgs args) {
var clone = (LogAttribute) MemberwiseClone();
return clone;
}
void IInstanceScopedAspect.RuntimeInitializeInstance() {
}
// Advices
public override void OnEntry(MethodExecutionArgs args) {
}
public override void OnSuccess(MethodExecutionArgs args) {
}
public override void OnException(MethodExecutionArgs args) {
}
public override void OnExit(MethodExecutionArgs args) {
}
public override void OnYield(MethodExecutionArgs args) {
}
public override void OnResume(MethodExecutionArgs args) {
}
}
我将它用于非静态和静态方法以及 类。但是现在我不能在静态类中使用IInstanceScopedAspect
!
我遇到错误:Error LA0203 Cannot apply instance-level aspect "LogAttribute" to static class "...".
改变了什么?我现在该怎么做?
这在 PostSharp 6.4 中是不允许的,因为可以以违反 C# 的静态 classes 定义(添加的实例成员等)的方式更改方面的目标 class。如果你需要 IInstanceScopedAspect
,现在正确的方法是有两个独立的方面,例如实例和静态方法。
实现此目标的最佳方法是拥有创建正确相位的 IAspectProvider
:
[PSerializable]
public class LogAttribute : MethodLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
if (targetElement is MethodBase method)
{
if (method.IsStatic)
yield return new AspectInstance(targetElement, new StaticLogAspect());
else
yield return new AspectInstance(targetElement, new InstanceLogAspect());
}
}
}
[PSerializable]
internal abstract class BaseLogAspect : IAspect
{
[OnMethodEntryAdvice]
[SelfPointcut]
public virtual void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine("Base");
}
}
[PSerializable]
internal class StaticLogAspect : BaseLogAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine("Static");
}
}
[PSerializable]
internal class InstanceLogAspect : BaseLogAspect, IInstanceScopedAspect
{
public object CreateInstance(AdviceArgs adviceArgs)
{
return new InstanceLogAspect();
}
public void RuntimeInitializeInstance()
{
}
public override void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine("Instance");
}
}
请注意,IInstanceScopedAspect
导致为每个目标实例分配一个方面对象 class。当您在方法上使用它时,此类方面可能会导致对象的内存占用量显着增加。
如果您的建议方法中需要与实例相关的信息,最好在类型上有一个 "central" 实例范围的方面。该方面存储实例信息并将接口引入目标class。然后方法级方面使用引入的接口来获取有关实例的信息。