2015-07-01 45 views
0

比方说,我有一群人的财产(名字,姓氏,地址,城市等)循环来填充类属性?

我拉数据来填补这些属性从Excel文件(使用优秀的EPPlus库),其中每个的列与Person属性相同,顺序相同。

有没有一种方法来遍历Class Person中的所有属性来填充它们?

目前,我这样做:

person.FirstName= worksheet.Cells[2, 1].Text; 
person.LastName= worksheet.Cells[2, 2].Text; 
person.Address= worksheet.Cells[2, 3].Text; 
person.City= worksheet.Cells[2, 4].Text; 
person.Age= worksheet.Cells[2, 5].Text; 
//repeat for a dozen more properties 

这似乎相当不雅。有一些我可以使用的循环吗?

+0

Cells集合是否包含映射回该属性的值?像'Cells [1,1]'等于“FirstName”一样?如果是这样,那么是的,你可以使用反射来遍历集合并将它们映射回对象的属性。 –

+0

单元格[1,X]是列名称(在EEPlus库中,它实际上看起来像单元格[y,x]) 。它们的水平顺序与我的类属性垂直相同。我的属性名称与列名完全不匹配(命名约定等)。 我对反射没有任何经验。你能为我指出正确的方向吗? –

+0

有很多关于如何在MSDN和Stack Overflow上使用反射的例子。见例如'Type.GetProperties()'方法。但请注意,特别是在输入数据和类属性名称之间没有确切的对应关系的情况下,这可能不易实现。如果您尝试使用反射并遇到麻烦,请提出一个问题,确切地说明您实际尝试过的内容,并包括对您遇到问题的明确具体解释。 –

回答

1

这里最大的障碍是如何自动将列索引与特定属性相关联的问题。即代码应该如何知道列索引1对应于FirstName属性。

可以从您班级的类型中检索PropertyInfo对象的列表。这些对象可以与您的类的实例一起使用来设置或获取属性值。因此,假设您有一些方法可以将列索引映射到特定属性,从而映射到特定的对象,则可以按照与列相同的索引(或更有可能)的顺序排列对象列表PropertyInfo ,列索引减1)。

但反思缓慢,坦率地说,可能会令人困惑和难以使用,特别是对于非专家。也很难让反思在速度上表现良好。

就我个人而言,我会坚持已有的。即明确地为合适的索引编写适当的分配。我所做的一个修改是,而不是在代码中使用文字,定义const值。例如:

const int firstNameColumn = 1; 
const int lastNameColumn = 2; 
// etc. 

void InitializeFromCell(Worksheet worksheet, int rowIndex) 
{ 
    person.FirstName = worksheet.Cells[rowIndex, firstNameColumn].Text; 
    person.LastName = worksheet.Cells[rowIndex, lastNameColumn].Text; 
    // etc. 
} 

您可以考虑提取从列映射到属性在一个单独的方法,这样至少你只需要编写一次代码:

void SetIndexedProperty(Person person, int propertyIndex, string value) 
{ 
    switch (propertyIndex) 
    { 
    case firstNameColumn: 
     person.FirstName = value; 
     break; 
    case lastNameColumn: 
     person.LastName = value; 
     break; 
    // etc. 
    } 
} 

void InitializeFromCell(Worksheet worksheet, int rowIndex) 
{ 
    for (int columnIndex = 1; columnIndex <= numberOfColumns; columnIndex++) 
    { 
     SetIndexedProperty(person, columnIndex, worksheet.Cells[rowIndex, columnIndex].Text); 
    } 
} 

或者,你可以抽象分配使用的Action<Person, string>代表的数组:

static readonly Action<Person, string>[] _propertyIndexers = 
{ 
    (person, value) => person.FirstName = value, 
    (person, value) => person.LastName = value, 
    // etc. 
} 

void InitializeFromCell(Worksheet worksheet, int rowIndex) 
{ 
    for (int columnIndex = 1; columnIndex <= numberOfColumns; columnIndex++) 
    { 
     _propertyIndexers[columnIndex - 1](person, worksheet.Cells[rowIndex, columnIndex].Text); 
    } 
} 

IMHO,任何上述将比反射一个更简单,更容易理解的方法。即使你在工作表数据的列名和你的实际属性名称之间有一个确切的一对一的对应关系,并且缺少这个,情况更是如此。 :)

+0

感谢您的详细提示。我非常喜欢使用const值进行代码可读性的想法 –