如何编写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<AspectInstance> 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
{
}
}
答案 0 :(得分:2)
这是一个工作示例。将此方面应用于类将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<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);
}
}
}
要使用属性,指定参数,我使用
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);
}
}