2011-11-05 55 views
2

不幸的是我仍在使用.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中沒有這種奢侈。

+2

這是不是很清楚你要完成什麼,但它是你使用不當的屬性可能。屬性與類型相關聯,而不與該類型的對象相關聯。如果你需要一個特定對象的自定義顯示格式,那麼你*有*使用普通屬性。 –

回答

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另一個屬性,只要你想它,你可以使用該財產,而不是名稱屬性,返回lenght例子FormattedName。 這將允許您保留您的財產附近的財產的格式版本。

+0

謝謝你的答覆。如果我的理解是正確的,你說什麼,我沒有獲得任何使用屬性。我想知道MS如何實現這一點[DisplayFormat(DataFormatString =「{0:C}」)] – user712923

+0

他們以我向你展示的方式......通過反思。 –

+0

而不是獲取值,但可能只能反射以獲取關聯的屬性而不是屬性值,但它取決於您的應用程序。 –

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; 
    } 
} 
+0

GetCustomAttributes()。OfType比使用Attribute.GetCustomAttribute慢,並且他沒有linq,因爲它是C#2.0。 –

+1

@SalvatorePreviti:如何精確地編碼外觀並不重要。這是屬性保存由其他類訪問的元數據的概念,而屬性本身實際上並不做任何事情。是的,你可以微觀優化(例如,通過將結果屬性保存在某處而不是每次通過反射訪問它),但這不是我的觀點。另外,使用.NET 2.0不能免除您使用LINQ的責任。你有沒有聽說過[LINQBridge](http://linqbridge.googlecode.com)? –

相關問題