2015-09-24 45 views
0

有沒有辦法使現有的類字段的集合?C#,製作類字段的集合

我有一個有很多字段/屬性的類有很多有意義的名字。

class ExampleClass 
{ 
    public string meaningfulName1 { get; set;} 
    public double meaningfulName2 { get; set;} 
    ... 
    public myOtherClass meaningfulNameN { get; set;} 
} 

我需要從外部(不是我的)程序中生成的文件讀取這些屬性的值。

由於有很多字段/屬性,讀取值並逐一分配它們似乎效率低下。所以我想要這些字段/屬性的集合。類似於

foreach (fieldReference in ExampleClass.fieldReferenceCollection) 
{ 
    readValueFromFile(fieldReference); 
} 

但是,如何保持所有名稱?

使用所有參數值而不是單獨的字段進行集合看起來合乎邏輯,但是字段名稱將會丟失。而且,考慮到字段的數量,如果可能的話,我們希望保留這些名稱以簡化進一步的開發。

所以我需要單獨的字段/屬性和它們的集合在同一時間可用。

字典集合並不是很快,afaik,因此參數名稱作爲值的鍵似乎也不完全適合。

我發現的另一個選擇是反射,但我不確定如何確定反射集合中的字段順序。字段順序作爲文件非常重要,我正在讀取值,沒有元數據,只是一系列十六進制值。反射似乎對於從文件中讀取值來說是過分的,而且它也很慢,afaik。

所以問題是:我應該怎麼做才能同時擁有類字段和它們的集合呢?

我的假設是錯誤的這項任務?有沒有其他方法可以將文件中的大量啞值讀入複雜對象?

P.S.我的第一個SO問題和英語是我的第二語言,所以我爲這些錯誤感到抱歉。

+0

不是假設解決方案太慢,而是寫下來,看看它們是否太慢。如果他們是*然後*你可以看看如何解決這些問題,如果不是,你有你的解決方案。 – Servy

+1

你正在閱讀什麼類型的文件? XML,JSON,INI?可能已經存在一個解析器,具體取決於您正在處理的內容。 – juharr

+0

反射比磁盤I/O慢嗎?我會嘗試。關於訂單:它不是你應該使用的東西(聲明訂單),只需在每個屬性上添加一個屬性並按順序對它們進行訂購。 –

回答

0

看起來像你會不得不使用反射來做你想做的。至於確定字段的順序,我建議使用自定義屬性標記屬性。

下面是一個例子。希望這會引導您找到您需要的解決方案。

namespace ConsoleApplication2 
{ 
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 
    public sealed class FileField : Attribute 
    { 
     public int Index { get; set; } 
     public FileField() { } 
    } 
    class ExampleClass 
    { 
     [FileField(Index = 0)] 
     public string meaningfulName1 { get; set; } 
     [FileField(Index = 2)] 
     public double meaningfulName2 { get; set; } 
     [FileField(Index = 1)] 
     public MyOtherClass meaningfulNameN { get; set; } 
    } 
    class MyOtherClass 
    { 
     public string Something { get; set; } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var exampleClassFieldProperties = GetExampleClassFieldProperties(); 

      var lines = File.ReadAllLines("datafile.txt"); 
      var records = new List<ExampleClass>(); 
      foreach (var line in lines) 
      { 
       var fields = line.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); 
       var record = new ExampleClass(); 
       for(int fieldIndex = 0; fieldIndex < fields.Length; fieldIndex++) 
       { 
        if (exampleClassFieldProperties.ContainsKey(fieldIndex)) 
        { 
         ReadValueFromFile(fields[fieldIndex], exampleClassFieldProperties[fieldIndex], record); 
        } 
       } 
       records.Add(record); 
      } 
      Console.WriteLine("Press any key to continue"); 
      Console.ReadKey(); 
     } 
     public static Dictionary<int, PropertyInfo> GetExampleClassFieldProperties() 
     { 
      var exampleClassFieldProperties = new Dictionary<int, PropertyInfo>(); 

      var properties = typeof(ExampleClass).GetProperties(); 
      foreach (var property in properties) 
      { 
       var attributes = property.GetCustomAttributes(false); 
       int index = 0; 
       foreach (var attribute in attributes) 
       { 
        if (attribute is FileField) 
        { 
         index = ((FileField)attribute).Index; 
         if (exampleClassFieldProperties.ContainsKey(index) == false) 
         { 
          exampleClassFieldProperties.Add(index, property); 
         } 
        } 
       } 
      } 

      return exampleClassFieldProperties; 
     } 
     public static void ReadValueFromFile(string field, PropertyInfo exampleClassField, ExampleClass record) 
     { 
      if (exampleClassField.PropertyType.Name == typeof(string).Name) 
      { 
       record.GetType().InvokeMember(exampleClassField.Name, 
        BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty, 
        Type.DefaultBinder, record, new object[] { field }); 
      } 
      else if (exampleClassField.PropertyType.Name == typeof(double).Name) 
      { 
       record.GetType().InvokeMember(exampleClassField.Name, 
        BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty, 
        Type.DefaultBinder, record, new object[] { double.Parse(field) }); 
      } 
      else if (exampleClassField.PropertyType.Name == typeof(MyOtherClass).Name) 
      { 
       var other = new MyOtherClass(); 
       // TO DO: Parse field to set properties in MyOtherClas 
       record.GetType().InvokeMember(exampleClassField.Name, 
        BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty, 
        Type.DefaultBinder, record, new object[] { other }); 
      } 
     } 
    } 
}