不幸的是我仍然在研究.NET 2.0。我之前没有创建过自定义属性。
我想创建一个CustomStringFormatAttribute
:。
如果一个类,比如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);
}
}
有什么建议吗?
注意:为了简洁起见,我使用了自动属性。我在.NET 2.0中没那么奢侈。
答案 0 :(得分:1)
抱歉,您无法访问属性中的类实例或属性信息。 您应该编写一个额外的方法,例如某个“静态”类中的静态方法,它允许您执行您想要执行的操作。
实施例...
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的属性,例如FormattedName,它可以根据需要返回长度,您可以使用该属性而不是Name属性。 这样您就可以将属性的格式化版本保留在您的财产附近。
答案 1 :(得分:0)
你需要反过来做。您的属性中不应该有任何逻辑,它应该只使用它包含的信息公开属性(例如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;
}
}