【问题标题】:.NET custom property attribute?.NET 自定义属性属性?
【发布时间】:2011-01-24 11:41:24
【问题描述】:

编辑: 我最好改写: 如何使用自定义属性将 Class 属性的 GET 实现转换为 /?(我已将实例化 vars (classname, propertyname) 添加到属性中,但我宁愿拥有这些当然是自动获取的。)

Public Class CustomClass
    <CustomAttributeClass(ClassName:="CustomClass", PropertyName = "SomeProperty")> _
    Public Property SomeProperty() as String
        Get() as String
            //This implementation should be handled by the attribute class
        End Get

        Set(Byval value as String)
            Me._someProperty = value
        End Set
    End Property
End Class

老问题:

我想为类创建一个自定义属性属性。我可以创建一个从 Attribute 派生的类,并用该属性“标记”该属性,但是从这里去哪里呢?

我有一个存储库,可以根据属性值快速获取数据。我想概括属性中属性的行为,但我不知道如何从这里开始......任何帮助都会被极大地接受!

Public Class CustomDataAttribute : Inherits Attribute
    Private _name As String

    Public Sub New(ByVal name As String)
        Me.Name = name
    End Sub

    Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            Me._name = value
        End Set
    End Property
End Class


Public Class CustomClass
    <CustomDataAttribute(Name:="CustomField")> _ 
    Public Property CustomField()
    End Property
End Class

【问题讨论】:

  • 从这里去哪里?你想去哪里?你想达到什么目的?
  • CustomClass 是一个数据类,它将数据存储在与之关联的表中。我想覆盖几个属性并将它们存储在一个单独的表中(以及来自其他需要从自己的表中取出数据的自定义类的其他属性)

标签: .net vb.net attributes custom-attributes


【解决方案1】:

这是一个在使用反射时帮助处理自定义属性的类。将类型作为参数传递给构造函数。

public class AttributeList : List<Attribute>
{
    /// <summary>
    /// Gets a list of custom attributes
    /// </summary>
    /// <param name="propertyInfo"></param>
    /// <returns></returns>
    public static AttributeList GetCustomAttributeList(ICustomAttributeProvider propertyInfo)
    {
        var result = new AttributeList();
        result.AddRange(propertyInfo.GetCustomAttributes(false).Cast<Attribute>());
        return result;
    }

    /// <summary>
    /// Finds attribute in collection by its own type or parents type
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T FindAttribute<T>() where T : Attribute
    {
        return (T)Find(x => typeof(T).IsAssignableFrom(x.GetType()));
    }

    /// <summary>
    /// Finds attribute in collection by its own type or parents type
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public List<T> FindAllAttributes<T>() where T : Attribute
    {
        return new List<T>(FindAll(x => typeof(T).IsAssignableFrom(x.GetType())).Cast<T>());
    }

    /// <summary>
    /// Finds attribute in collection by its own type or parents type
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public List<T> FindAllAttributes<T>(Type implementsType) where T : Attribute
    {
        return new List<T>(FindAll(x => implementsType.IsAssignableFrom(x.GetType())).Cast<T>());
    }

    public bool IsAttributeSet<T>() where T : Attribute
    {
        return FindAttribute<T>() != null;
    }

    public TValue GetValueFromAttributeOrDefault<TAttr, TValue>(Func<TAttr, TValue> func, TValue defaultValue) 
        where TAttr : Attribute
    {
        var attribute = FindAttribute<TAttr>();
        return attribute == null ? 
            defaultValue : 
            func(attribute);
    }
}

【讨论】:

    【解决方案2】:

    从您的 cmets 到上一个答案,我想您会发现 .NET 属性并不像您希望的那样灵活。

    您问“是否有一些基本属性属性具有诸如 onGet 和 onSet 之类的事件?” - 不;属性与其目标没有内置交互,无论是方法还是类。事实上,你甚至无法在运行时告诉属性的目标是什么。你必须先知道目标(类、方法、属性等),然后查询哪些属性装饰它。

    其次,在您查询属性之前,不会真正创建属性。当您调用GetCustomAttributes 时,运行时系统会评估程序集元数据并实例化指定的属性。如果连续调用两次,会得到两组相同的属性。

    回到您的另一个问题:如果您想知道何时设置或检索用您的属性装饰的属性,您必须在所有相关类上实现 INotifyPropertyChanged,编写代码来搜索所有类对于在程序集加载时标记有该属性的属性,然后构建一些交互性,将PropertyChanged 事件连接到您需要触发的任何代码。 (这只会通知您set 操作,而不是get。)

    不知道这是否有帮助,但你去吧。 :-)

    【讨论】:

    • 一些非常有用的辅助信息,对于那些没有在属性方面做得比自定义授权属性更多的人。但是我仍然不知道从哪里开始...我只需要更改一些已经存在的业务类以使某些属性本地化...我不能使用默认的资源提供程序,因为它存储了视图的路径使资源本地化。但是我需要本地化(关于本地资源,而不是本地化!哈哈)基于业务类的资源,而不是基于视图......
    【解决方案3】:

    您必须使用反射来发现该属性。在您的情况下,您将从 PropertyInfo.GetCustomAttributes() 获得它。

    使用属性的难点在于找到合适的执行模型来实际使用它们。诸如编译器、设计器或序列化对象的类之类的东西是显而易见的。属性的可用性从那里迅速下降。当您尝试在实际需要虚拟属性的情况下使用属性时,这几乎总是错误的选择。检索属性值非常昂贵,比检索属性值贵许多数量级。仅当反射代码在人工时运行(如编译器)或成本与收益或开销相比微不足道时(在任何类型的 I/O 操作中都很常见)时才使用它们。

    【讨论】:

    • 您能否详细说明:我想将本地化应用于属性自定义业务对象。属性的覆盖/归因是一个非常糟糕的方法吗?如果每个对象只有一个属性,我将创建一个接口来定义要本地化的属性。然而,每个对象的多个属性都需要本地化。有什么建议吗?
    • “非常”昂贵并不完全正确。技术上比方法调用更昂贵,是的。但是面向属性的模型在整个 .NET 世界中用于对性能极其敏感的系统中。在系统中使用属性不会成为瓶颈。
    • 但是我不知道在哪里使用反射器。看着我想要完成的事情似乎很奇怪......难道没有一些基本属性属性有一些事件,如 onGet 和 onSet?
    • @ropstah:我无法理解您的用例。本地化是一个 UI 细节,它不应该适用于业务对象。 WF、WPF 和 ASP.NET 等 .NET UI 框架已经很好地支持本地化。先看看那里。
    • 我不明白如何将默认资源提供程序(我实现为 SQL 资源提供程序)用于业务类中的本地化内容(这些本地化资源需要在更多地方使用,而不仅仅是意见)。还是所有不特定于单个视图的资源都应该是全局资源?
    猜你喜欢
    • 1970-01-01
    • 2012-02-15
    • 1970-01-01
    • 2017-05-31
    • 2011-03-27
    • 1970-01-01
    • 2015-01-19
    • 2020-12-19
    相关资源
    最近更新 更多