如何在.NET 2.0中实现自定义属性?
不幸的是我仍在使用.NET 2.0。我以前没有创建过自定义属性。 我想创建一个CustomStringFormatAttribute
:。如何在.NET 2.0中实现自定义属性?
如果一个类,说Customer.Name,具有:
MaxLength=30
ActualLength=10
我需要与空的空间填充它,直到它达到30
我还需要一个属性,我可以格式日期像DisplayDataFormat
我创建的属性内的财产的实际价值以下,但我如何获得?
public class Customer
{
[CustomStringFormatAttribute(30)]
public string Name { get; set; }
//todo:customDateAttribute
public DateTime StartDate { get; set; }
}
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
public sealed class CustomStringFormatAttribute : Attribute
{
private readonly int maxLength;
public CustomStringFormatAttribute(int maxLength)
{
MaxLength = maxLength;
}
public int MaxLength { get; private set; }
//?Should I override ToString
public override string ToString()
{
return Format();
}
private string Format()
{
//simplified version of my formatting for brevity
string source = "value from the property of the class.";//How do I get access to the actual value of the property within the attribute?
const char paddingChar = ' ';
return source.PadLeft(maxLength, paddingChar);
}
}
有什么建议?
注:I”使用自动属性简洁。我在.NET 2.0中没有这种奢侈。
对不起,你不能访问类的实例或您的属性中的属性信息。 你应该在一些“静态”类中编写一个额外的方法,例如一个静态方法,它允许你做你想做的事情。
例....
public static string FormatProperty(object instance, PropertyInfo property)
{
CustomStringFormatAttribute attrib = Attribute.GetCustomAttribute(property, typeof(CustomStringFormatAttribute)) as CustomStringFormatAttribute;
return property.GetValue(instance, null).ToString().PadLeft(attrib.MaxLength, ' ');
}
public static string FormatProperty(object instance, string propertyName)
{
return FormatProperty(instance, instance.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance));
}
但是,这是非常不舒服,而且出奇的慢,因为使用反射来通过属性信息获取属性值。
要访问属性的属性,你需要的PropertyInfo。
public static int GetPropertyMaxLength(PropertyInfo property)
{
CustomStringFormatAttribute attrib = Attribute.GetCustomAttribute(property, typeof(CustomStringFormatAttribute)) as CustomStringFormatAttribute;
return attrib != null ? attrib.MaxLength : int.MaxValue;
}
public static int GetPropertyMaxLength(Type type, string propertyName)
{
return GetPropertyMaxLength(type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance));
}
让我们假设我们把这些函数放在属性中。 然后我们想重写我们的Customer类中的ToString方法。
public override string ToString()
{
return CustomStringFormatAttribute.FormatProperty(this, "Name");
}
的问题,这是当然的速度,它使用的名字,很慢,而且重构反射,你不会有一个编译时警告或错误,如果“名称”属性不存在,你会运行时只能得到一个异常。我建议你使用另一种机制。
有了你可以使用lambda表达式直接由酒店本身获得你的财产信息的语言的新版本,但因为你是C#2.0中这是不可能的。
另一种解决方案可以是:添加,而不是所谓的FormattedXXX另一个属性,只要你想它,你可以使用该财产,而不是名称属性,返回lenght例子FormattedName。 这将允许您保留您的财产附近的财产的格式版本。
谢谢你的答复。如果我的理解是正确的,你说什么,我没有获得任何使用属性。我想知道MS如何实现这一点[DisplayFormat(DataFormatString =“{0:C}”)] – user712923
他们以我向你展示的方式......通过反思。 –
而不是获取值,但可能只能反射以获取关联的属性而不是属性值,但它取决于您的应用程序。 –
你需要反过来做。你的属性中不应该有任何逻辑,它应该简单地暴露属性与它包含的信息(例如MaxLength属性)。然后你Customer
类应该访问由CustomStringFormatAttribute
提供的信息,并相应地格式化:
private string m_Name;
public string Name
{
get
{
var formatAttribute = typeof(Customer).GetCustomAttributes(false)
.OfType<CustomStringFormatAttribute>
.SingleOrDefault();
if (formatAttribute != null)
return m_Name.PadLeft(formatAttribute.MaxLength);
return m_Name;
}
set
{
m_Name = value;
}
}
GetCustomAttributes()。OfType比使用Attribute.GetCustomAttribute慢,并且他没有linq,因为它是C#2.0。 –
@SalvatorePreviti:如何精确地编码外观并不重要。这是属性保存由其他类访问的元数据的概念,而属性本身实际上并不做任何事情。是的,你可以微观优化(例如,通过将结果属性保存在某处而不是每次通过反射访问它),但这不是我的观点。另外,使用.NET 2.0不能免除您使用LINQ的责任。你有没有听说过[LINQBridge](http://linqbridge.googlecode.com)? –
这是不是很清楚你要完成什么,但它是你使用不当的属性可能。属性与类型相关联,而不与该类型的对象相关联。如果你需要一个特定对象的自定义显示格式,那么你*有*使用普通属性。 –