c# - 用 String[] 填充结构?

标签 c#

我正在解析一个 CSV 文件并将数据放在一个结构中。我正在使用来自 this questionTextFieldParser除了返回 String[] 之外,它的工作原理非常棒。目前我有以下丑陋的过程:

String[] row = parser.ReadFields();
DispatchCall call = new DispatchCall();
if (!int.TryParse(row[0], out call.AccountID)) {
    Console.WriteLine("Invalid Row: " + parser.LineNumber);
    continue;
}
call.WorkOrder = row[1];
call.Description = row[2];
call.Date = row[3];
call.RequestedDate = row[4];
call.EstStartDate = row[5];
call.CustomerID = row[6];
call.CustomerName = row[7];
call.Caller = row[8];
call.EquipmentID = row[9];
call.Item = row[10];
call.TerritoryDesc = row[11];
call.Technician = row[12];
call.BillCode = row[13];
call.CallType = row[14];
call.Priority = row[15];
call.Status = row[16];
call.Comment = row[17];
call.Street = row[18];
call.City = row[19];
call.State = row[20];
call.Zip = row[21];
call.EquipRemarks = row[22];
call.Contact = row[23];
call.ContactPhone = row[24];
call.Lat = row[25];
call.Lon = row[26];
call.FlagColor = row[27];
call.TextColor = row[28];
call.MarkerName = row[29];

除了 AccountID 是 int 之外,该结构由所有 String 字段组成。它们不是强类型的,这让我很恼火,但现在让我们先看一下。鉴于 parser.ReadFields() 返回一个 String[] 是否有更有效的方法来填充结构(可能转换一些值,例如 row[0] 需要将数组中的值变成 int)?

**编辑:**我忘记提到的一个限制可能会影响什么样的解决方案将起作用是这个结构是[Serializable]并且将被发送其他地方的 Tcp。

最佳答案

您的里程可能会因它是否是更好的解决方案而有所不同,但您可以使用反射并定义一个 Attribute用于标记结构成员的类。该属性将数组索引作为参数。然后使用反射从正确的数组元素分配值。

你可以这样定义你的属性:

[AttributeUsage(AttributeTargets.Property)]
public sealed class ArrayStructFieldAttribute : Attribute
{
    public ArrayStructFieldAttribute(int index)
    {
        this.index = index;
    }

    private readonly int index;

    public int Index {
        get {
            return index;
        }
    }
}

这意味着该属性可以简单地用于关联 int名为 Index 的值有属性(property)。

然后,您可以使用该属性在结构中标记您的属性(只是一些示例行):

[ArrayStructField(1)]
public string WorkOrder { // ...

[ArrayStructField(19)]
public string City { // ...

然后可以使用 Type 设置值您的结构类型的对象(您可以使用 typeof 运算符获取它):

foreach (PropertyInfo prop in structType.GetProperties()) {
    ArrayStructFieldAttribute attr = prop.GetCustomAttributes(typeof(ArrayStructFieldAttribute), false).Cast<ArrayStructFieldAttribute>().FirstOrDefault();
    if (attr != null) {
         // we have found a property that you want to load from an array element!
        if (prop.PropertyType == typeof(string)) {
            // the property is a string property, no conversion required
            prop.SetValue(boxedStruct, row[attr.Index]);
        } else if (prop.PropertyType == typeof(int)) {
            // the property is an int property, conversion required
            int value;
            if (!int.TryParse(row[attr.Index], out value)) {
                Console.WriteLine("Invalid Row: " + parser.LineNumber);
            } else {
                prop.SetValue(boxedStruct, value);
            }
        }
    }
}

此代码遍历结构类型的所有属性。对于每个属性,它会检查上面定义的自定义属性类型。如果存在这样的属性,并且属性类型为 stringint , 该值是从相应的数组索引中复制的。

我正在检查 stringint属性,因为这是您在问题中提到的两种数据类型。即使您只有一个包含 int 的特定索引现在的值,如果此代码准备好将任何索引作为字符串或 int 属性进行处理,则有利于可维护性。

请注意,为了处理更多类型,我建议不要使用 if 链和 else if ,而是一个 Dictionary<Type, Func<string, object>>将属性类型映射到转换函数。

关于c# - 用 String[] 填充结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12009104/

相关文章:

c# - 何时调用 SaveChanges

使用 OleDbConnection 的 Open 方法时,C# Excel 不会自行关闭

c# - 空传播 - 第二次空检查

c# - MVC3 按属性名称本地化显示名称属性

c# - 如何在Winform中输入韩文?

c# - 在 ASP.NET Core Web API 中创建 RDLC 报告

c# - 仅在传递整数时使用命名参数

c# - 使用 winform checkbox 进行 linq 查询

c# - 如何将对象转换为不同程序集中的匿名类型?

c# - Linq 查询到 IEnumerable<T> 扩展方法