如何使用PostSharp属性注入属性?

如何编写PostSharp方面以将属性应用于类? 我正在考虑的场景是需要使用DataContract属性进行修饰的WCF实体(或域对象)。 它还应该有一个Namespace属性。 像这样:

 using System.Runtime.Serialization; namespace MWS.Contracts.Search.V1 { namespace Domain { [DataContract(Namespace = XmlNamespaces.SchemaNamespace)] public class PagingContext { [DataMember] public int Page { get; set; } [DataMember] public int ResultsPerPage { get; set; } [DataMember] public int MaxResults { get; set; } } } } 

在上面的例子中,您可以看到我想要输出的样子。 它具有应用于类的DataContract属性。 手工完成这项工作既乏味又不独特。 我真的只想写一个可以应用于我的“域”命名空间的方面。 然后它将为我应用序列化相关属性。 这样我就可以专注于开发实体对象,而不用担心序列化的细节。

我在PostSharp的网站上找到了用于在方法之前,之后和代替方法注入代码的文档。 然而,我正在寻找的是一种将属性注入类型的方法。


这是解决方案!

 using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.Serialization; using PostSharp.Aspects; using PostSharp.Extensibility; using PostSharp.Reflection; namespace MWS.Contracts.Aspects { // We set up multicast inheritance so the aspect is automatically added to children types. [MulticastAttributeUsage(MulticastTargets.Class, Inheritance = MulticastInheritance.Strict)] [Serializable] public sealed class AutoDataContractAttribute : TypeLevelAspect, IAspectProvider { private readonly string xmlNamespace; public AutoDataContractAttribute(string xmlNamespace) { this.xmlNamespace = xmlNamespace; } // This method is called at build time and should just provide other aspects. public IEnumerable ProvideAspects(object targetElement) { var targetType = (Type) targetElement; var introduceDataContractAspect = new CustomAttributeIntroductionAspect( new ObjectConstruction(typeof (DataContractAttribute).GetConstructor(Type.EmptyTypes))); introduceDataContractAspect.CustomAttribute.NamedArguments.Add("Namespace", xmlNamespace); var introduceDataMemberAspect = new CustomAttributeIntroductionAspect( new ObjectConstruction(typeof (DataMemberAttribute).GetConstructor(Type.EmptyTypes))); // Add the DataContract attribute to the type. yield return new AspectInstance(targetType, introduceDataContractAspect); // Add a DataMember attribute to every relevant property.))) foreach (var property in targetType.GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance) .Where(property => property.CanWrite && !property.IsDefined(typeof (NotDataMemberAttribute), false))) yield return new AspectInstance(property, introduceDataMemberAspect); } } [AttributeUsage(AttributeTargets.Property)] public sealed class NotDataMemberAttribute : Attribute { } } 

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

这是一个有效的例子。 将此方面应用于类将XmlIgnore属性应用于尚未应用XmlElement或XmlAttribute的任何公共属性。 诀窍是使用Postsharp内置的CustomAttributeIntroductioinAspect。 您只需要实例化一个指定属性类型和构造函数详细信息的实例,然后创建一个提供程序以将其应用于目标。

 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 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); } } } 

要使用属性,指定参数,我使用

  public class MyAspect : TypeLevelAspect, IAspectProvider { public IEnumerable ProvideAspects(object targetElement) { yield return Create(mi, "Value"); } private AspectInstance Create(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); } }