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

标签 c# .net postsharp aop

如何编写 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/

相关文章:

.net - 引用的依赖关系未复制到输出目录

c# - 如何将 PostSharp 与最小起订量一起使用?

mono - 有人在 Mono 下使用过任何 AOP 产品吗?

c# - 在 PostSharp 的 OnMethodBoundaryAspect 中的 OnEntry 中获取 Controller 的基类成员

c# - WPF DataGrid CellEditEnded 事件

c# - 无法加载反序列化所需的类型

c# - Entity Framework 4 : How to enforce WHERE clause order in generated query

C# 如何对静态方法使用 AOP?

c# - Web Api 在发生异常时总是返回 http 状态码 200

.net - 如何创建 Silverlight 3 主题?