2015-09-24 25 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 }); 
      } 
     } 
    } 
}