PostSharp not only allows aspects to be applied in code, but also through XML. This is accomplished by adding them to your project's postsharp.config file. See Configuring Projects Using postsharp.config for information on these files.
Adding aspects through XML gives the advantage of applying aspects without modifying the source code, which can be useful in some legacy projects. It allows you to apply aspects to several or all projects in your solution without manually including a source file in each project.
Specifying an attribute in XML
namespace MyCustomAttributes
{
// We set up multicast inheritance so the aspect is automatically added to children types.
[MulticastAttributeUsage( MulticastTargets.Class, Inheritance = MulticastInheritance.Strict )]
[PSerializable]
public sealed class AutoDataContractAttribute : TypeLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects( object targetElement )
{
Type targetType = (Type) targetElement;
var introduceDataContract = new CustomAttributeIntroductionAspect(
new ObjectConstruction( typeof(DataContractAttribute).GetConstructor( Type.EmptyTypes )! ) );
var introduceDataMember = new CustomAttributeIntroductionAspect(
new ObjectConstruction( typeof(DataMemberAttribute).GetConstructor( Type.EmptyTypes )! ) );
// Add [DataContract] to the type.
yield return new AspectInstance( targetType, introduceDataContract );
// Add [DataMember] to the public properties declared by the type.
foreach ( var property in targetType.GetProperties( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly ) )
{
if ( property.CanWrite )
{
yield return new AspectInstance( property, introduceDataMember );
}
}
}
}
}
Normally AutoDataContractAttribute would be applied to Customer in code as follows:
namespace MyNamespace
{
[AutoDataContract]
class Customer
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
}
}
Using XML instead, you can remove the custom attribute from source code and instead specify a Multicast element in the PostSharp project file, which is named postsharp.config and placed in the same directory as the project file:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.postsharp.org/1.0/configuration">
<Multicast xmlns:my="clr-namespace:MyCustomAttributes;assembly:XmlMulticasting">
<my:AutoDataContractAttribute AttributeTargetTypes="MyNamespace.Customer" />
</Multicast>
</Project>
In this snippet, the xmlns:my attribute associates a prefix with an XML namespace, which must be mapped to the .NET namespace and assembly where the custom attribute classes are defined. In this example, the aspect is defined in the namespace MyCustomAttributes of the assembly XmlMulticasting:
<Multicast xmlns:my="clr-namespace:MyCustomAttributes;assembly:XmlMulticasting">
The next line then specifies the custom attribute to apply and the elements to which to apply it:
<my:AutoDataContractAttribute AttributeTargetTypes="MyNamespace.Customer" />
The XML element name must be the name of a class inside the .NET namespace and assembly as defined by the XML namespace. Attributes of this XML element map to public properties or fields of this class.
When the Customer class has no custom attribute in source code, but the postsharp.config file above is in the project directory, a program that reads the custom attributes of Customer by reflection prints:
Customer: [DataContract] = True
FirstName: [DataMember] = True
LastName: [DataMember] = True
Note that any property inherited from MulticastAttribute can be used here to apply the aspect to several classes at a time. See the section Adding Aspects to Multiple Declarations Using Attributes for details about these properties.
See Also
Other Resources
Adding Aspects to Multiple Declarations Using Attributes
Configuring Projects Using postsharp.config