0

假设您有一个具有以下结构的 CSV 文件

 LINE1:  ID,Description,Value
 LINE2:  1,Product1,2
 LINE3:  ,,3
 LINE4:  ,,4
 LINE5:  2,Product2,2
 LINE6:  ,,3
 LINE7:  ,,5 

有对应的FileHelpers定义类

[DelimitedRecord(",") ]
[IgnoreFirst(1)] 
public class Product
{
    public int ID { get; set; }
    public string Description { get; set; }

    [FieldConverter(ConverterKind.Decimal)]
    public decimal Val{ get; set; }
}

如何使用FileHelpers来返回对象,使每个对象都被完全填充?

让我澄清一下,目前,使用的结果engine.ReadFile只会产生完全填充的第 2 行和第 5 行的对象,这是有道理的,因为这些字段是空白的。但是,第 3 行和第 4 行的对象也应该具有与第 1 行相同的ID和。每一行的字段都应该保持不变。我不确定数据的正确术语是什么,但它似乎“部分标准化”。DescriptionValue

我目前解决这个问题的方法如下使用AfterRead事件。我对事件、事件处理程序、委托等没有很好的掌握,所以我正在寻找一种使用 FileHelpers 来实现这一目标的替代方法。它也显得非常笨重。

    // call the csv repo using the ffg lines within a console app
    var repo2 = new CSVRepositoryBase<Product>();
    repo2.AfterRead +=new AfterReadHandler<object>(repo2_AfterRead);
    var products = repo2.Read("some file path");

    public static Product PreviousRecord { get; set; }

    private static void repo2_AfterRead
        (EngineBase engine, FileHelpers.Events.AfterReadEventArgs<object> e)
    {
        var record = (Product)e.Record;

        if (PreviousRecord == null)
        {
            PreviousRecord = new Product();
            PreviousRecord.ID = record.ID;
        }

        if (String.IsNullOrEmpty(record.ID)) // newline record = blank row
        {
            record.ID = PreviousRecord.ID;
        } 
        PreviousRecord.ID = record.ID;

    }


public class CSVRepositoryBase<T> where T : class
{
    // shorten for brevity 

    public IEnumerable<T> Read(string fileName){/*snip*/ }

    #region Events
    public event AfterReadHandler<object> AfterRead
    {
        add { engine.AfterReadRecord += value; }
        remove { engine.AfterReadRecord -= value; }
    }
    #endregion 
}
4

1 回答 1

2

您可以尝试使用 AfterRead 的接口而不是这样的事件。

如果我理解正确,您需要执行以下操作:

[DelimitedRecord(",") ]
[IgnoreFirst(1)] 
public class Product
:INotifyRead
{
    public int? ID;
    public string Description;

    [FieldConverter(ConverterKind.Decimal)]
    public decimal? Val;

    private static Product Previuous;

    public void AfterRead(EngineBase engine, string line)
    {
        if (!ID.HasValue && Previous != null)
              this.ID = Previus.ID;

        if (!Val.HasValue && Previous != null)
              this.Val= Previus.Val;

        Previuous = this;
    }
}

希望这可以帮助

于 2010-10-15T14:06:42.107 回答