将文件读取到自定义类构造函数

时间:2014-01-14 15:14:40

标签: c# .net class file-io constructor

我有一个看起来像这样的文本文件:

Name One, 123, 13.88, 12.25
Name Two, 321, 12.56, 10.75

我需要将它读入一个数组(不能是数组列表),其中包含我创建的自定义类,如下所示:

class Stuff
{
    //Stuffconstructor (w/ args)
    public Stuff(string name, int number, decimal rate, double hours)
    {
        System.Console.WriteLine("this constructor has been called");
    }
}

我不太确定如何在c#中执行此操作。

2 个答案:

答案 0 :(得分:2)

var parsedList = new List<Stuff>();
string[] lines = System.IO.File.ReadAllLines(@"C:\input.txt");
foreach (var line in lines)
{
    var lineSplit = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
    var stuff = new Stuff(lineSplit[0], Int32.Parse(lineSplit[1]), decimal.Parse(lineSplit[2]), double.Parse([3])  );
    parsedList.Add(stuff);
}
Stuff[]  arrayOfStuff = parsedList.ToArray();

答案 1 :(得分:0)

你看起来它可能是一个非常通用的例子......你可能想要一些更强大和可扩展的东西。那么,让我向您介绍反思

注意

此解决方案使用反射 ...这意味着一些事情:

  • 这不适合胆小的人...这对新的程序员来说可能看起来很奇怪。
  • 它的表现并不精通。反射可能比正常代码 LITTLE 慢......
  • 为简单起见,我们假设您有一个公共构造函数
  • 同样为了简单起见,我们假设构造函数只有具有方法Parse()或类型String的参数。

<强>解决方案

public static IEnumerable<T> Extract<T>(String path)
{
  var parseList = buildParser(typeof(T));

  foreach (string line in File.ReadLines(path))
  {
    var tokens = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
    var args = parseList.Zip(tokens, (parser, value) => parser(value));

    yield return (T)Activator.CreateInstance(typeof(T), args.ToArray());
  }
}

private static IEnumerable<Func<String, Object>> buildParser(Type t)
{
  // For now, we're going to assume you only have one public constructor.
  var ci = t.GetConstructors().First();

  foreach (var pi in ci.GetParameters())
  {
    var parser = fetchParseMethod(pi.ParameterType);
    Func<String, Object> boxingParser;

    if (parser != null)
      boxingParser = value => parser.Invoke(null, new Object[] { value });
    else
      boxingParser = value => value;

    yield return boxingParser;
  }
}

private static System.Reflection.MethodInfo fetchParseMethod(Type t)
{
  return (from mi in t.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)
          let parms = mi.GetParameters()
          where mi.Name == "Parse" && parms.Length == 1 && parms.First().ParameterType == typeof(String)
          select mi).FirstOrDefault();
}

然后使用这样的代码:

foreach(var stuff in Extract<Struff>(@"C:\blah.txt"))
{
  // Do something with stuff
}

简要概述

这可能看起来有点相当......但实际上很简单:

  1. 我们首先看一下所需类型的构造函数(Stuff
  2. 然后我们浏览构造函数的每个ParameterType并获取Parse()方法。
  3. 然后,我们对文本行的每个元素使用Parse()方法将其转换为Object
  4. 有了这个,我们可以动态创建一个对象(Stuff)。
  5. 虽然这可能对你来说太过分了......我很开心创造它,希望我们都能从中学到一些东西。此外,该解决方案非常灵活。如果稍后向构造函数添加参数,则自动选择它。