.NET自定义属性属性?

时间:2010-03-06 16:08:20

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

编辑: 我最好改写一下: 如何将Class属性的GET实现转换为/使用自定义属性?(我已经为属性添加了即时变量(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

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

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

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

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

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

不知道这是否有用,但你去了。 : - )

答案 2 :(得分:0)

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

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