How to inject an attribute using a PostSharp attribute?

See http://www.sharpcrafters.com/blog/post/PostSharp-Principals-Day-12-e28093-Aspect-Providers-e28093-Part-1.aspx

Here is a working example. Applying this aspect to a class will apply the XmlIgnore attribute to any public property that does not already have XmlElement or XmlAttribute applied to it. the trick is using the CustomAttributeIntroductioinAspect that is built in to Postsharp. You just need to instantiate an instance specifying the attribute type and contructor details, then create a provider to apply it to the target(s).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PostSharp.Extensibility;
using PostSharp.Aspects;
using PostSharp.Reflection;
using System.Xml.Serialization;

namespace ApplyingAttributes
{
    [MulticastAttributeUsage(MulticastTargets.Field | MulticastTargets.Property,
                            TargetMemberAttributes = MulticastAttributes.Public | MulticastAttributes.Instance)]
    public sealed class AddXmlIgnoreAttribute : LocationLevelAspect, IAspectProvider
    {
        private static readonly CustomAttributeIntroductionAspect customAttributeIntroductionAspect =
            new CustomAttributeIntroductionAspect(
                new ObjectConstruction(typeof(XmlIgnoreAttribute).GetConstructor(Type.EmptyTypes)));

        public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
        {
            LocationInfo memberInfo = (LocationInfo)targetElement;

            if (memberInfo.PropertyInfo.IsDefined(typeof(XmlElementAttribute), false) ||
                memberInfo.PropertyInfo.IsDefined(typeof(XmlAttributeAttribute), false))
                yield break;

            yield return new AspectInstance(memberInfo.PropertyInfo, customAttributeIntroductionAspect);
        }
    }

}

To use attributes, specifying parameters, I use

 public class MyAspect : TypeLevelAspect, IAspectProvider
{
    public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
    {
        yield return Create<MethodInfo>(mi, "Value");

    }

    private AspectInstance Create<T>(T target, string newName)
    {
        var x = new CustomAttributeIntroductionAspect(
            new ObjectConstruction(typeof(NewMethodName).GetConstructor(new Type[] { typeof(string) }), new object[] { newName })
            );

        return new AspectInstance(target, x);
    }
}

Leave a Comment