How can I write a PostSharp aspect to apply an attribute to a class? The scenario I\'m considering is a WCF entity (or domain object) that needs to be decorated with the
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);
}
}