Присвоение переменных экземпляра, полученных путем отражения в обобщенном методе - PullRequest
0 голосов
/ 22 октября 2019

У меня есть данные в текстовых файлах со значениями, разделенными табуляцией (TSV), которые я хочу прочитать и (в конце концов) сохранить в таблицах базы данных. С файлами TSV каждая строка содержит одну запись, но в одном файле запись может иметь 2 поля, в другом файле 4 поля и т. Д. Я написал рабочий код для обработки записей с 2 ​​полями, но я подумал, что это может быть хорошимслучай для общего метода (или два), а не писать новые методы для каждого вида записи. Однако я не смог закодировать это из-за 2 проблем: я не могу создать новый объект для хранения данных записи, и я не знаю, как использовать отражение для общего заполнения переменных экземпляра моих объектов.

Я посмотрел несколько других похожих постов, в том числе Возможность получения данных для объекта с помощью отражения и linq

Ниже приведен код, который работает (это в Windows, если это имеет значение)а также код, который не работает.

public class TSVFile
{
    public class TSVRec
    {
        public string item1;
        public string item2;
    }

    private string fileName = "";

    public TSVFile(string _fileName)
    {
        fileName = _fileName;
    }

    public TSVRec GetTSVRec(string Line)
    {
        TSVRec rec = new TSVRec();

        try
        {
            string[] fields = Line.Split(new char[1] { '\t' });

            rec.item1 = fields[0];
            rec.item2 = fields[1];
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show("Bad import data on line: " + 
                Line + "\n" + ex.Message, "Error",
                System.Windows.Forms.MessageBoxButtons.OK,
                System.Windows.Forms.MessageBoxIcon.Error);
        }

        return rec;
    }

    public List<TSVRec> ImportTSVRec()
    {
        List<TSVRec> loadedData = new List<TSVRec>();
        using (StreamReader sr = File.OpenText(fileName))
        {
            string Line = null;
            while ((Line = sr.ReadLine()) != null)
            {
                loadedData.Add(GetTSVRec(Line));
            }
        }

        return loadedData;
    }

    // *** Attempted generic methods ***
    public T GetRec<T>(string Line)
    {
        T rec = new T();  // compile error!
        Type t = typeof(T);

        FieldInfo[] instanceVars = t.GetFields();

        string[] fields = Line.Split(new char[1] { '\t' });

        for (int i = 0; i < instanceVars.Length - 1; i++)
        {
            rec. ??? = fields[i];   // how do I finish this line???
        }

        return rec;
    }

    public List<T> Import<T>(Type t)
    {
        List<T> loadedData = new List<T>();
        using (StreamReader sr = File.OpenText(fileName))
        {
            string Line = null;
            while ((Line = sr.ReadLine()) != null)
            {
                loadedData.Add(GetRec<T>(Line));
            }
        }

        return loadedData;
    }
}

Я видел строку T rec = new T ();в вышеупомянутом посте, но это не работает для меня ...

Буду признателен за любые предложения о том, как сделать эту работу, если это возможно. Я хочу больше узнать об использовании рефлексии с обобщениями, поэтому я хочу не только понять, как, но и почему.

1 Ответ

1 голос
/ 24 октября 2019

Хотелось бы, чтобы @EdPlunkett опубликовал свое предложение как ответ, а не как комментарий, чтобы я мог пометить его как ответ ...

Подводя итог: делать то, что я хочу, естьнет необходимости в «Назначении переменных экземпляра, полученных путем отражения в универсальном методе». На самом деле, у меня может быть универсальное решение без использования универсального метода:

public class GenRec
{
    public List<string> items = new List<string>();
}

public GenRec GetRec(string Line)
{
    GenRec rec = new GenRec();

    try
    {
        string[] fields = Line.Split(new char[1] { '\t' });

        for (int i = 0; i < fields.Length; i++)
            rec.items.Add(fields[i]);
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show("Bad import data on line: " + Line + "\n" + ex.Message, "Error",
            System.Windows.Forms.MessageBoxButtons.OK,
            System.Windows.Forms.MessageBoxIcon.Error);
    }

    return rec;
}

public List<GenRec> Import()
{
    List<GenRec> loadedData = new List<GenRec>();
    using (StreamReader sr = File.OpenText(fileName))
    {
        string Line = null;

        while ((Line = sr.ReadLine()) != null)
            loadedData.Add(GetRec(Line));
    }

    return loadedData;
}

Я только что проверил это, и оно работает как шарм!

Конечно, это не помогаетмне научиться писать универсальные методы или использовать рефлексию, но я возьму это ...

...