C # подход к отображению входных файлов динамически - PullRequest
3 голосов
/ 08 февраля 2010

Я пытаюсь найти наилучший способ сопоставления входных файлов, таких как файлы XLS или CSV, с объектами в системе. Позвольте мне немного подробнее остановиться на этом. У меня есть следующие объекты:

Компания Контакт

Каждая имеет переменные переменные, такие как:

Адрес Телефонные номера Сообщения электронной почты и т.д.

Входной файл, который я могу получить, варьируется, иногда будут заголовки столбцов, иногда нет, расположение столбцов и номера будут меняться время от времени. Это может выглядеть следующим образом:

COMPANY         - CONTACT       - ADDRESS       - PHONE
----------------------------------------------------------------------
company1          contact1        address1        phone1
company1          contact2        address2
company2          contact3                        phone2
                  contact4        address3

Выше показано, что «company» будет иметь «addres1» и «phone1», связанные с компанией, «contact1» - это собственный объект, но родительский объект «company1».

То же самое относится и к "contact2" (кроме телефона).

«contact4» не имеет родительского объекта, поэтому «address3» принадлежит контакту, а не компании.

До сих пор я думал о том, чтобы иметь следующие объекты:

Сопоставления - (здесь я не уверен, как это реализовать. В нем должно быть указано, как столбцы должны сопоставляться с переменными, принадлежность / иерархия - например, у компании есть адрес)

IMappingLoader - (загружает объекты сопоставления)

- XmlMappingLoader

- DbMappingLoader

IDataLoader - (загружает данные в набор данных)

- XLSLoader

- CSVLoader

Таким образом, сопоставления будут загружены, данные загружены в набор данных и возвращены правильные объекты.

Часть, в которой я не уверен, что лучший способ приблизиться - это сделать часть сопоставлений. Как определить, какой столбец должен принадлежать какому объекту.

Спасибо за любые советы.

Jon

1 Ответ

1 голос
/ 08 февраля 2010

Ваши парсеры должны будут знать о ваших столбцах .... в противном случае он не сможет сопоставить данные с конкретными свойствами объекта. Если, конечно, вы не введете класс indexed-свойств, в котором вы могли бы хранить информацию в зависимости от порядка ее чтения.

Вы должны создать фабрику синтаксического анализатора, и на основании расширения файла вы вернете правильный анализатор для задания, например

public class Record 
{ 
    private Dictionary<int, string> items = new Dictionary<int, string>(); 
    private int propCount; 

    public Record(int size) 
    { 
        // populate array with empty strings 
        for(int i = 0; i <= size -1; i++) 
            items.Add(i, String.Empty); 
        propCount = size; 
    } 

    public string this[int index] 
    { 
        get { return items[index]; } 
        set { items[index] = value; } 
    } 

    public int PropertyCount { get { return propCount; } } 
}

public interface IRecordParser 
{ 
    string FileName { get; set; } 
    string[] GetHeadings(); 
    bool HasHeaders { get; set; } 
    void GoToStart(); 
    Record ParseNextRecord(); 
} 

public abstract class RecordParser 
{ 
    public string FileName { get; set; } 
    public bool HasHeaders { get; set; } 
    public abstract string[] GetHeadings(); 
    public abstract void GoToStart(); 
    public abstract Record ParseNextRecord();     
} 

public class ExcelRecordParser : RecordParser, IRecordParser 
{ 
    public ExcelRecordParser() 
    { 
    } 

    public override string[] GetHeadings() 
    { 
        if (HasHeaders)  
            // return column headings
        else 
            // return default headings from settings file
    } 

    public override void GoToStart() 
    { 
        // navigate to first row (or +1 if HasHeaders is true) 
    } 

    public override Record ParseNextRecord() 
    { 
        var headers = GetHeadings(); 
        var r = new Record(headers.Length);

        // enumerate rows, then for each row do...
        for(int i = 0; i <= headers.Length - 1; i++) 
            r[i] = row[i];

        return r;
    } 
}

public class CsvRecordParser : RecordParser, IRecordParser 
{ 
    public CsvRecordParser() 
    { 
    } 

    public override string[] GetHeadings() 
    { 
        if (HasHeaders) 
            // return first row split as headings
        else 
            // return default headers from settings file
    } 

    public override void GoToStart() 
    { 
        // navigate to start of file (or +1 if HasHeaders is true) 
    } 

    public override Record ParseNextRecord() 
    { 
        var headers = GetHeadings(); 
        var r = new Record(headers.Length);

        // enumerate lines, then for each line do...
        for(int i = 0; i <= headers.Length - 1; i++) 
            r[i] = line[i];

        return r;
    } 
} 

public static class RecordParserFactory 
{ 
    public static IRecordParser Create(string ext) 
    { 
        switch (ext) 
        { 
            case ".xls": 
                return new ExcelRecordParser() as IRecordParser; 
            case ".csv": 
                return new CsvRecordParser() as IRecordParser;
            default:
                return null;
        } 
    } 
}

Использование

// would return an instance of CSV Parser
string file = @"C:\Data\MyRecords.csv";
IRecordParser parser = RecordParserFactory.Create(System.IO.Path.GetExtension(file));

// would return an instance of Excel Parser
string file = @"C:\Data\MyRecords.xls";
IRecordParser parser = RecordParserFactory.Create(System.IO.Path.GetExtension(file));

Это позволит вам добавить другие парсеры, если формат файла изменится в будущем, например, XML, бинарный и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...