在dotnet / .NET中实现自定义属性的最佳方法是什么?

时间:2009-06-10 14:06:21

标签: c# .net attributes

我真的不懂属性。我读过各种各样的书籍和他们的帖子,但我不明白。

由于我不理解它们,我也不明白如何有效地使用它们。

1)你能给我一个关于属性是什么的好定义吗?它用于什么?

2)你能否在C#中给我一个如何制作和使用自定义属性的好代码示例?

7 个答案:

答案 0 :(得分:11)

我可以给你一个例子,但与这篇好文章相比,它会显得很苍白:

Defining and Using Custom Attribute Classes in C#

  

复杂的,组件式的   企业期待的发展   现代软件开发人员需要   比设计灵活性更大   过去的设计方法。   微软的.NET Framework使   广泛使用属性来提供   通过什么增加了功能   被称为“声明性”编程。   属性增强了灵活性   软件系统因为它们的推动   松散的功能耦合。   因为您可以创建自己的自定义   属性类然后采取行动   他们,你可以利用松散   耦合你的属性的力量   自己的目的。

答案 1 :(得分:9)

假设您有一个包含一系列属性的类,您将使用反射来完成这些属性。任何字符串都可能需要验证,以检查它们是否不超过一定数量。

然后,您可以使用默认的整数构造函数和整数属性/字段创建TextLength属性。然后,您可以在类中的每个字符串属性上读取属性,并将属性值的长度与属性中指定的数字进行比较。

代码:

public class TextLengthAttribute : Attribute
{
    private int length;
    public int Length { get { return length; } set { length = value; } }

    public TextLengthAttribute(int num) { this.length = num; }
}

public class MyClass
{
    [TextLength(10)]
    public string Property1;
    [TextLength(20)]
    public string Property2;
}

public class ClassReader
{
     public static void Main()
     {
          MyClass example = MyClass.GetTestData();

          PropertyInfo[] props = typeof(MyClass).GetProperties();
          foreach (PropertyInfo prop in props)
          {
               if (prop.ValueType == typeof(String) 
               {
                    TextLengthAttribute[] atts = 
                      (TextLengthAttribute)[]prop.GetCustomAttributes(
                           typeof(TextLengthAttribute), false);
                    if (prop.GetValue(example, null).ToString().Length > 
                         atts[0].Length) 
                        throw new Exception(prop.name + " was too long");
               }
          }
     }
}

注意:未经测试

答案 2 :(得分:3)

我们要求在特定排序顺序的下拉列表中显示枚举值。我们使用自定义属性实现。

[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Field, AllowMultiple = false)]
public class EnumSortAttribute : Attribute
{
    public int SortOrder;
    public bool SortByDescription;
}

[EnumSort(SortByDescription=true)]
public enum EnumSortByDescription
{
    [Description("enO")]
    One = 1,
    [Description("2")]
    Two = 2,
    Three = 3,
    [Description("rouF")]
    Four = 4
}

public enum EnumCustomSortOrder
{
    [EnumSort(SortOrder = 3)]
    One = 1,
    [EnumSort(SortOrder = 1)]
    Two = 2,
    [EnumSort(SortOrder = 2)]
    Three = 3
}

答案 3 :(得分:2)

有很多例如log4PostSharp。他们使用属性来引入AOP行为。

这是我曾经使用过的一个属性,为属性提供一个单位(如秒,米,......)

[AttributeUsage( AttributeTargets.Property )]
public sealed class UnitAttribute : Attribute
{
  public UnitAttribute( Unit unit )
  {
    Unit = unit;
  }

  public Unit Unit { get; private set; }
}

它用于属性,如:

[Unit( Unit.Meter )]
public float Distance { get; set; }

您可以稍后检索该属性以在GUI上显示它。

答案 4 :(得分:2)

属性用于提供有关任何成员(字段,类等)的元数据。

您可以通过继承Attribute来创建它们,并使用它来使用它们 Attribute.GetCustomAttribute 方法

默认属性的一个示例是PrincipalPermissionAttribute,它仅允许经过身份验证的用户访问某些资源。例如:

[PrincipalPermission (SecurityAction.Demand, Role="Supervisor")]
public class DoTheThingPage : Page
{
    ////
}

在此示例中,我们有一个ASP.NET页面,只能由属于“Supervisor”角色的经过身份验证的用户查看。

(此属性由ASP.NET中的安全子系统自动读取)

另请注意,未使用类名的“属性”部分,这是.NET中的约定。

答案 5 :(得分:1)

答案 6 :(得分:1)

属性只是将附加信息(元数据)添加到类,结构或某个成员的一种方法。其他代码可以检索此元数据,以便做出一些决定。

来自.NET的

最简单的示例SerializableAttribute。它表示稍后可以通过BinaryFormatter对类进行序列化。

这是另一个例子 - 我们可以使用ImmutableAttribute在代码中标记一些类,以表明它们没有任何可变字段,并且可以用于多线程操作:

[Immutable]
public sealed class ProcessingMessage
{
    //... some code that should be thread-safe

}

然后,我们可以创建一个单元测试,找到具有该属性的所有类,并确保they are immutable indeed

[Test]
public void Immutable_Types_Should_Be_Immutable()
{
  var decorated = GlobalSetup.Types
    .Where(t => t.Has<ImmutableAttribute>());

  foreach (var type in decorated)
  {
    var count = type.GetAllFields().Count(f => !f.IsInitOnly && !f.IsStatic);
    Assert.AreEqual(0, count, "Type {0} should be immutable", type);
  }
}