编辑: 我最好改写一下: 如何将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
答案 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);
}
}