2009-07-20 60 views
0

我試圖使用反射來設置某些OpenXML類型的屬性(例如對齊方式)。通過枚舉所有可能分配一個值是直接的:使用通用類型和隱式轉換的反射

// attr is an XmlAttribute, so .Name and .Value are Strings 
if (attr.Name == "Val") 
{ 
    if (element is Justification) 
    { 
     ((Justification)element).Val = (JustificationValues)Enum.Parse(typeof(JustificationValues), attr.Value); 
      return; 
    } 
    else 
    { 
     // test for dozens of other types, such as TabStop 
    } 
} 

是什麼讓這很難通過反射做的是: 1)型瓦爾屬性是EnumValue <牛逼>,所以我不知道如何提取要作爲第一個參數傳遞給Enum.Parse的類型。 2)有一個從實際枚舉類型到EnumValue類型的隱式轉換,我不知道如何用反射調用。

我想的代碼最終看起來像:

PropertyInfo pInfo = element.GetType().GetProperty(attr.Name); 
Object value = ConvertToPropType(pInfo.PropertyType, attr.Value); /* this 
    would return an instance of EnumValue<JustificationValues> in this case */ 
pInfo.SetValue(element, value, null); 

如何實現ConvertToPropType?還是有更好的解決方案?

感謝

編輯: 我得到了一個解決方案使用埃裏克的建議的工作,但它依靠便捷的事實枚舉的類型名稱可以從該節點的類型名稱派生(「理由」 - >「JustificationValues」 )。不過,我仍然很好奇如何在一般情況下解決這個問題。

編輯2: GetGenericArguments讓我在那裏的其餘部分。謝謝。

+0

你有沒有看到更新我的答案?它演示瞭如何從屬性類型獲取枚舉類型。 – 2009-07-21 06:22:09

回答

4

如果屬性值只是一個字符串,我假設你已經有一些方法可以確定字符串是從一個特定的枚舉中識別一個值。在你的例子中你有它硬編碼,所以我不知道這是你想要什麼或你想改變。

假設你知道這是一個枚舉,你知道哪些枚舉,你已經知道如何獲取包含正確enum類型的裝箱值,對象爲您的片段。

現在,如果我假設EnumValue<T>有一個構造函數,需要一個T

Type genericType = typeof(EnumValue<>); 
Type concreteType = genericType.MakeGenericType(typeof(JustificationValues)); 

現在concreteType是類型EnumValue<JustificationValues>

從這裏你可以得到一個構造函數,希望是一個需要JustificationValues參數,和Invoke它。

更新

啊,我看你現在在做什麼。您使用XML屬性名稱來選擇C#屬性。您需要能夠檢測該屬性是否屬於EnumValue<T>類型,並找出T是什麼。

PropertyInfo p = // ... get property info 

Type t = p.GetType(); 

if (t.IsGenericType && 
    t.GetGenericTypeDefinition == typeof(EnumValue<>)) 
{ 
    Type e = t.GetGenericArguments()[0]; // get first (and only) type arg 

    // e is the enum type... 

試試看。

+0

我一般不知道枚舉類型,它取決於元素的類型。我不知道MakeGenericType,但我不認爲我能夠使用它,直到我弄清楚如何從類型EnumValue中提取類型T bmm6o 2009-07-20 20:15:48

1

.Net 4.0增加了對後期隱含或顯式轉換的支持。這在開源框架ImpromptuInterface中簡化了,它的靜態方法叫做InvokeConvert。在你的理想例如它的工作是這樣的:

PropertyInfo pInfo = element.GetType().GetProperty(attr.Name); 
Object value = Impromptu.InvokeConvert(attr.Value, pInfo.PropertyType); 
pInfo.SetValue(element, value, null); 
1

這可能只與基本類型的工作,但它是不夠好,我在做什麼

PropertyInfo pInfo = element.GetType().GetProperty(attr.Name); 
Object value = System.Convert.ChangeType(attr.Value, pInfo.PropertyType); 
pInfo.SetValue(element, value, null);