我正在尝试一次从CSV文件中读取一行数据。第一行,列标题,确定每一行中的数据类型。我已经知道所有数据都属于我的项目中有一个名为UserModel的类,但是我试图通过不将数据硬编码到UserModel字段来做到这一点。我能够阅读前两行,并正确创建用户模型的第一个实例。但是当我尝试阅读第三行时,事情就崩溃了。我正在使用词典,并且在阅读前几行时尝试使用创建的词典的实例。意思是使用Dictionary实例中的键顺序,只用下一组数据更新值,但是我无法弄清楚为什么该组数据不与正确的键对齐。
我在这里得到了一些很棒的代码并使用了它。 DictionaryToObject()方法就是其中之一。我认为我使用的循环超过了我的需要,并且不了解使用其他方式来访问某些数据结构,例如字符串数组,列表和字典。我是新手,可能在尝试获得所需结果时使用了错误的数据结构,甚至使用了一些不必要的代码。
public class MyData
{
BindingList<UserModel> users = new BindingList<UserModel>();
UserModel currentUser = new UserModel();
public BindingList<UserModel> GetUsers()
{
string[] lines = File.ReadAllLines("StandardDataSet.csv");
// Add error handing to make sure all lines have four enteris
foreach (string line in lines.Skip(1))
{
//I am not sure how to handle the first line that is a header
string [] values = line.Split(',').Select(x => x.Trim()).ToArray();
currentUser.FirstName = values[0];
currentUser.LastName = values[1];
int.TryParse(values[2], out int age);
currentUser.Age = age;
bool.TryParse(values[3], out bool alive);
currentUser.IsAlive = alive;
users.Add(currentUser);
}
return users;
}
private static T DictionaryToObject<T>(IDictionary<string, object> dict) where T : new()
{
T t = new T();
PropertyInfo[] properties = t.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
if (!dict.Any(x => x.Key.Equals(property.Name, StringComparison.InvariantCultureIgnoreCase)))
continue;
KeyValuePair<string, object> item = dict.First(x => x.Key.Equals(property.Name, StringComparison.InvariantCultureIgnoreCase));
Type tPropertyType = t.GetType().GetProperty(property.Name).PropertyType;
Type newT = Nullable.GetUnderlyingType(tPropertyType) ?? tPropertyType;
//if (item.Value is '0') Convert.ToBoolean(Convert.ToInt32(item.Value));
object newA = Convert.ChangeType(item.Value, newT);
t.GetType().GetProperty(property.Name).SetValue(t, newA, null);
}
return t;
}
public BindingList<UserModel> GetUsersAdvanced()
{
users = new BindingList<UserModel>();
var dict= new Dictionary<string,object>();
string[] lines = File.ReadAllLines("AdvancedDataSet.csv");
var header = lines.First().Split(',');
var data = lines.Skip(1).First().Split(',');
for (int i = 0; i < header.Length; i++)
{
if (data[i] == "0" || data[i] == "1")
{
Boolean IsAlive = Extensions.ToBoolean(data[i]);
dict.Add(header[i], IsAlive);
}
else
//if (data[i]!= "0" || data[i]!="1")
dict.Add(header[i], data[i]);
}
currentUser = DictionaryToObject<UserModel>(dict);
var dictCopy = new Dictionary<string, object>(dict);
var dictConcurrent = new ConcurrentDictionary<string, object>(dict);
foreach (var line in lines.Skip(1))
{
if (line != null) data = line.Split(',');
foreach (var key in dict.Keys)
{
int i = 0;
if (data[i] == "0" || data[i] == "1")
{
Boolean IsAlive = Extensions.ToBoolean(data[i]);
dictCopy[key] = IsAlive;
i++;
continue;
}
else
dictCopy[key] = data[i];
i++;
}
currentUser = DictionaryToObject<UserModel>(dictCopy);
users.Add(currentUser);
currentUser = new UserModel();
}
return users;
}
答案 0 :(得分:0)
正如人们的评论所说,我还建议使用现有的库。它们通常还支持您在代码中执行的到对象的数据映射和数据转换。因此,请先尝试一两个。
怎么样:
顺便说一下,按照字典中项目的顺序,您可以阅读原因here
出于枚举目的,字典中的每个项目都被视为代表值及其键的KeyValuePair结构。物品的退还顺序是不确定的。
那么,如何将列标题保留在列表中呢?这样,您可以保留订单。代码如下。
但是请仅将其作为订购商品的示例。再次,先尝试一些库,然后您将看到更酷的功能并获得更简洁的代码。
public BindingList<UserModel> GetUsersAdvanced()
{
users = new BindingList<UserModel>();
string[] lines = File.ReadAllLines("AdvancedDataSet.csv");
var cols = lines.First().Split(',').ToList();
// validate column name duplication here!
foreach (var line in lines.Skip(1))
{
if (line != null) data = line.Split(',');
for (var i = 0; i < cols.Count(); i++)
{
var key = cols[i];
var dict = new Dictionary<string, object>();
if (data[i] == "0" || data[i] == "1")
{
Boolean IsAlive = Extensions.ToBoolean(data[i]);
dict.Add(key, IsAlive);
}
else
dict.Add(key, data[i]);
var currentUser = DictionaryToObject<UserModel>(dict);
users.Add(currentUser);
}
return users;
}
}