Search code examples
c#aoppostsharp

How do I get Aspects applied to certain element (e.g. for LocationInfo type parameter, or PropertyInfo)?


TL/DR:

How do I get Aspects applied to certain element, e.g. for LocationInfo type parameter, or PropertyInfo ?

Elaboration:

I want to find all dependencies of properties/fields during RuntimeInitialize

[Serializable]
public class NotifyPropertyChangedAspect : LocationInterceptionAspect {
    /* ... stuff ... */
    public override void RuntimeInitialize(LocationInfo locationInfo)
    {
        foreach(var attr in locationInfo.PropertyInfo.GetCustomAttributes(false)
                                .OfType<DependsOnAttribute>();){
            this.SaveDependencies(attr.Dependencies);
        }
        base.RuntimeInitialize(locationInfo);
    }
    /* ... things ... */
}

The code above works for attributes:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class DependsOnAttribute : Attribute {
    public string[] Dependencies { get; set; }
    public DependsOnAttribute(params string[] dependencies) { Dependencies = dependencies; }
}

[NotifyPropertyChangedAspect]
class MyClass {
    public string Name { get; set; }
    [DependsOnAttribute("Name")]
    public bool IsChanged { get; set; }
}

But not for aspects:

[Serializable]
public class DependsOnAspect : LocationLevelAspect {
    public string[] Dependencies { get; set; }
    public DependsOnAspect(params string[] dependencies) { Dependencies = dependencies; }
}

[NotifyPropertyChangedAspect]
class MyClass {
    public string Name { get; set; }
    [DependsOnAspect("Name")]
    public bool IsChanged { get; set; }
}

Solution

  • Aspects are special case of Multicast attributes. In brevity, Multicast attributes are removed from the assembly after it is processed by PostSharp. To override this behavior, you need to specify the following:

    [MulticastAttributeUsage(PersistMetaData = true)]
    public class DependsOnAspect : LocationLevelAspect { ... }
    

    This will tell PostSharp that you need the aspect attribute to be present at runtime.