gpt4 book ai didi

c# - 如何使用 PostSharp 属性注入(inject)属性?

转载 作者:太空狗 更新时间:2023-10-29 20:37:24 25 4
gpt4 key购买 nike

如何编写 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 的网站上找到了有关在方法之前、之后和而不是注入(inject)代码的文档。然而,我正在寻找的是一种将属性注入(inject)类型的方法。


这是解决方案!

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
{
}
}

最佳答案

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

这是一个工作示例。将此方面应用于类会将 XmlIgnore 属性应用于尚未应用 XmlElement 或 XmlAttribute 的任何公共(public)属性。诀窍是使用 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);
}
}

关于c# - 如何使用 PostSharp 属性注入(inject)属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7851365/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com