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

9

我不太理解属性。我已经阅读了各种书籍和文章,但我仍然不明白。

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

1)你能给我一个好的定义,说明属性是什么以及它的用途是什么吗?

2)你能给我一个C#的好代码示例,说明如何创建和使用自定义属性吗?

7个回答

11

我可以举一个例子,但与这篇精美的文章相比会相形见绌:

在C#中定义和使用自定义特性类

现代软件开发所需的复杂组件式开发需要比过去更大的设计灵活性。 Microsoft的.NET Framework通过使用属性来提供所谓的“声明性”编程,为此做出了广泛的应用。属性通过促进功能的松耦合,增强了软件系统的灵活性。因为您可以创建自己的自定义属性类,然后对其进行操作,所以您可以利用属性的松散耦合能力来实现自己的目的。


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

注意:未经测试

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
}

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上显示它。


2
一个属性用于提供有关任何成员(字段、类等)的元数据。
您可以通过继承Attribute来创建它们,并使用Attribute.GetCustomAttribute方法来使用它们。
默认属性的一个例子是PrincipalPermissionAttribute,它仅允许经过身份验证的用户访问某些资源。例如:
[PrincipalPermission (SecurityAction.Demand, Role="Supervisor")]
public class DoTheThingPage : Page
{
    ////
}

在这个例子中,我们有一个ASP.NET页面,只能被属于“主管”角色的经过身份验证的用户查看。
(此属性由ASP.NET中的安全子系统自动读取)
另请注意,“类名”的“属性”部分未被使用,这是.NET中的约定。

1

属性只是一种向类、结构或某些成员添加附加信息(元数据)的方式。其他代码可以检索此元数据以做出某些决策。

最简单的例子是来自.NET的SerializableAttribute。它表示该类稍后可以由BinaryFormatter序列化。

这里有另一个例子 - 我们可以使用ImmutableAttribute标记我们代码中的某些类,以指示它们没有任何可变字段,并且适用于多线程操作:

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

}

然后,我们可以创建一个单元测试来查找所有具有该属性的类,并确保它们确实是不可变的(译注:链接未提供)

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接