4

编辑:我最好改写: 如何使用自定义属性将 Class 属性的 GET 实现转换为 /?(我已经将实例化变量(类名,属性名)添加到属性中,但是我当然希望这些自动获取。)

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
4

3 回答 3

2

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

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

于 2010-03-06T16:16:39.647 回答
2

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

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

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

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

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

于 2010-03-06T16:47:43.223 回答
0

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

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

于 2010-03-18T03:04:43.293 回答