2012-01-20 51 views
3

我得到這個代碼,工程(簡體):獲取PropertyInfo的默認值而不實例化對象?

Assembly lib = Assembly.LoadFile("C:\\mydll.dll"); 
var libType = lib.GetTypes(); 
Type mvType = libType[0]; 
PropertyInfo WidthProperty = mvType.GetProperty("Width"); 

但後來,我想訪問默認值有類似的代碼

var WidthPropertyValue = WidthProperty.GetValue(???, null); 

的事情是,我們可以」 T使用Activator.CreateInstance實例化對象導致構造函數需要整個巨大的項目被加載工作......無論如何,這不是解決這個問題的關鍵。 問題是,是否有可能使用此策略訪問默認方式? 以另一種方式可能嗎? 完全不可能?

+4

你說的是什麼「默認值」?一個設計師會通過一個屬性或者在構造函數中分配的初始值來服從嗎?一個例子在這裏真的很有用。 –

+1

我會說構造函數的初始值,但我可以訪問所有這些默認值而不實例化對象?!? –

+0

如果在構造函數中賦值,唯一知道它的人是構造函數本身。所以我沒有看到創建實例的另一種方式。 –

回答

1

如果彙編代碼是可訪問的,我會建議使用Attribute定義默認值。

否則我不認爲它是可能的。屬性默認值不是程序集元數據的一部分(默認值概念不存在,因此DefaultValueAttribute存在),所以我不確定你可以想象它沒有創建對象的實例。它可以是任何東西:後臺字段的默認值,在構造函數中設置的一些值,它可以基於一些環境條件等。

更新:我已經看到一些答案/評論指向創建屬性類型的默認類型。屬性默認值是特定於實現的,而不是類型特定的。在許多情況下,它們可能會重合,但事實並非如此。

+0

是的,這是我的問題的重點,但我覺得這是不可能的,我希望有一個神奇的解決方案,因爲它有時會發生在這裏:) 關於編輯源代碼,我們無法做到這一點,但我會爲未來記住這一點! –

3

你需要說明你的意思是「默認值」......它是屬性類型的默認值嗎?在這種情況下,它是空的引用類型和值類型是使用默認構造函數創建一個實例:

static object GetDefaultValue(PropertyInfo prop) 
{ 
    if (prop.PropertyType.IsValueType) 
     return Activator.CreateInstance(prop.PropertyType); 
    return null; 
} 

如果你的意思是「與DefaultValueAttribute聲明的價值」,你可以這樣獲取:

static object GetDefaultValue(PropertyInfo prop) 
{ 
    var attributes = prop.GetCustomAttributes(typeof(DefaultValueAttribute), true); 
    if (attributes.Length > 0) 
    { 
     var defaultAttr = (DefaultValueAttribute)attributes[0]; 
     return defaultAttr.Value; 
    } 

    // Attribute not found, fall back to default value for the type 
    if (prop.PropertyType.IsValueType) 
     return Activator.CreateInstance(prop.PropertyType); 
    return null; 
} 

如果你想分配給構造屬性的值,就沒有辦法得到它,而無需創建類(當然,你可以反編譯代碼的實例,但它不太容易.. )

+0

不錯,謝謝... –

1

如果在第th e構造函數,並且實際上不能調用構造函數,所以提取值並不容易。這是因爲該值實際上嵌入在構造函數的代碼中。

如果您真的很勇敢並且有很多時間在您的手上,您可以嘗試使用Cecil這樣的工具直接檢查IL。如果屬性是簡單類型(INT,雙,字符串,等等),那麼你可以做到以下幾點:

如果正在構造通過現場設置:

  1. 確定的字段名稱財產。你可以根據編碼慣例猜出一個名字(不是很漂亮,但是它可能會根據你的工具的意圖完成工作),或者你可以進一步檢查屬性getter來查看它使用的字段。即使這可能是棘手的,如果屬性不僅僅是返回值。

  2. 檢查構造函數代碼並查找對該字段的引用。如果構造函數調用設置默認值的其他方法,這可能會很複雜。

  3. 一旦你找到了Stfld感興趣的領域,應立即看它上面的恆定值(Ldc_I4,Ldc_R4,Ldc_R8或Ldstr。)

如果正在通過在構造一個屬性設置:

  1. 確定屬性設置器並查找代碼中對setter的調用。

  2. 與現場案例一樣,在調用之前立即檢查以查看加載的常量值。

如果你真的想試試這個,我建議創建各種類型的構造,並率先在ILDASM檢查代碼,以獲取編譯代碼時的樣子的想法。在一般情況下,自動確定默認值將非常困難,但對於「常見」情況下可以實現,這可能足以滿足您的需要。

+0

我的PropertyInfo的類型是不透明的,但是我們所討論的內容顯然超出了我們想要做的事情,但是我肯定會看一看它 –