2013-03-26 50 views
0

我的案例值文本總是等於相關OSResultStruct代碼中的「我現在已經實現並正在工作的方式」。因此,例如,如果案例是確定的,則屬性是OSResultStruct。 OSEdition。c#消除開關要求

是否有可能做類似下面的代碼行?如果是這樣,那麼我可以用一行代碼替換我的switch語句。

lstNewItems[i].sItemValue = OSresult.OSResultStruct."lstNewItems[i].sItemName.ToString().ToUpper()"; 

的方式,我有現在implimented並正在

switch (lstNewItems[i].sItemName) 
     { 
      case "osedition": 
      lstNewItems[i].sItemValue = OSresult.OSResultStruct.OSEdition; 
      break; 
      case "osbuild": 
      lstNewItems[i].sItemValue = OSresult.OSResultStruct.OSBuild; 
      break; 
      case "osmajor":  
      //..... 

回答

2

嘗試反思: -

OSresult.OSResultStruct.GetType().GetProperty(lstNewItems[i].sItemName,BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(OSresult.OSResultStruct, null) 

對於一個更通用的方法: -

定義的擴展類: -

public static class ClassExtensions 
    { 
     public static TRes GetPublicPropertyValue<T,TRes>(this T queryObject, string propertyMatch) 
      where T : class,new() 
      where TRes : new() 

     { 
      return (TRes)typeof(T).GetProperty(propertyMatch, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(queryObject, null); 
     } 
    } 

如下用於任何實例化的類型: -

OSresult.OSResultStruct.GetPublicPropertyValue<yourtype,yourreturntype>(attribName); 
+0

當我做這個 lstNewItems [I] .sItemValue = OSresult.OSResultStruct.GetType()的getProperty( lstNewItems [i] .sItemName).GetValue(OSresult.OSResultStruct,null).ToString(); 我得到錯誤對象引用未設置爲對象的實例。注意我添加了方法.tostring() – user1438082 2013-03-26 02:34:52

+0

我如何忽略上述alexi推薦的情況? – user1438082 2013-03-26 02:40:59

+1

使用綁定標誌,並看到GetProperty(lstNewItems [i] .sItemName,System.Reflection.BindingFlags.IgnoreCase) – PSL 2013-03-26 02:43:31

1

你可以使用反射 - 按名稱獲取屬性訪問器(Type.GetProperty)得到一個作爲你的名字時,(你需要指定IgnoreCase似乎都是小寫)和使用訪問器的屬性的GetValue

4

不會更短,但...您可以編寫和擴展方法和屬性。然後將該屬性添加到每個枚舉成員並通過屬性中的字符串解析它。這將使它成爲一條線並且可重複使用。

一些代碼澄清 - 我說,這是不會成爲短:)

private static readonly Dictionary<DriveTrain, DriveTrainKind> DriveTrainKindMap = 
    Enums.GetValues<DriveTrain>().ToDictionary(d => d, d => d.GetDriveTrainKind()); 

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] 
public sealed class DriveTrainKindAttribute : Attribute 
{ 
    public DriveTrainKindAttribute(DriveTrainKind kind) 
    { 
     Kind = kind; 
    } 

    public DriveTrainKind Kind { get; private set; } 
} 

public static class ExtensionMethods 
{ 
    public static DriveTrainKind GetDriveTrainKind(this DriveTrain value) 
    { 
     var fieldInfo = typeof(DriveTrain).GetField(value.ToString()); 
     var attributes = fieldInfo.GetCustomAttributes(typeof(DriveTrainKindAttribute), false) 
            .Cast<DriveTrainKindAttribute>(); 
     return attributes.Select(a => a.Kind).SingleOrDefault(); 
    } 
} 

public enum DriveTrainKind : byte 
{ 
    ConventionalOrHybrid = 0, 
    PluginHybrid = 1, 
    BatteryElectric = 2, 
} 

public enum DriveTrain : short 
{ 
    [Description("konv_otto"), DriveTrainKind(DriveTrainKind.ConventionalOrHybrid)] 
    ConventionalGasoline = 0, 

    [Description("konv_diesel"), DriveTrainKind(DriveTrainKind.ConventionalOrHybrid)] 
    ConventionalDiesel = 1, 
    ... 
} 
+1

雖然反射很聰明,但它不能被編譯器檢查編譯時間(這就是爲什麼你要使用編譯語言,對嗎?)。使用具有屬性的擴展方法是編譯時間c hecked。如果屬性的數量很大,請務實並使用反射,但要確保單元測試所有可能的值。 – cfeduke 2013-03-26 02:21:22

+1

@cfeduke這是正確的。儘管該開關中字符串的正確性也不是編譯時可檢查的。所以這兩件事都缺乏相同的IMO。這是我在Java中使用C#缺少的很酷功能之一 - 枚舉。 – Schultz9999 2013-03-26 04:31:17

+1

我也喜歡這個 - 反射應該謹慎使用 – NSGaga 2013-03-26 12:09:38