C# 将文件读取到自定义类构造函数
我有一个如下所示的文本文件:C# 将文件读取到自定义类构造函数,c#,.net,class,file-io,constructor,C#,.net,Class,File Io,Constructor,我有一个如下所示的文本文件: Name One, 123, 13.88, 12.25 Name Two, 321, 12.56, 10.75 foreach(var stuff in Extract<Struff>(@"C:\blah.txt")) { // Do something with stuff } 我需要将其读入一个数组(不能是数组列表),其中包含我创建的自定义类,该类如下所示: class Stuff { //Stuffconstructor (w/ a
Name One, 123, 13.88, 12.25
Name Two, 321, 12.56, 10.75
foreach(var stuff in Extract<Struff>(@"C:\blah.txt"))
{
// Do something with stuff
}
我需要将其读入一个数组(不能是数组列表),其中包含我创建的自定义类,该类如下所示:
class Stuff
{
//Stuffconstructor (w/ args)
public Stuff(string name, int number, decimal rate, double hours)
{
System.Console.WriteLine("this constructor has been called");
}
}
我不太清楚如何在c#中实现这一点。var parsedList=new List();
string[]lines=System.IO.File.ReadAllLines(@“C:\input.txt”);
foreach(行中的var行)
{
var lineSplit=line.Split(新[]{',},StringSplitOptions.RemoveEmptyEntries);
var stuff=newstuff(lineSplit[0]、Int32.Parse(lineSplit[1])、decimal.Parse(lineSplit[2])、double.Parse([3]);
添加(东西);
}
Stuff[]arrayOfStuff=parsedList.ToArray();
您所拥有的可能是一个非常通用的示例。。。你可能想要一些更健壮和可扩展的东西。因此,让我向您介绍反思
注意
此解决方案使用反射。。。这意味着几件事:
- 这不是为胆小的人准备的。。。对于一个新的程序员来说,这可能看起来很奇怪
- 这不是对性能的理解。反射可能比正常代码慢一点
- 为简单起见,我们假设您有一个公共构造函数
- 此外,为了简单起见,我们假设构造函数只有具有方法
或类型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();
}
公共静态IEnumerable提取(字符串路径)
{
var parseList=buildParser(typeof(T));
foreach(File.ReadLines(路径)中的字符串行)
{
var tokens=line.Split(新[]{',},StringSplitOptions.RemoveEmptyEntries);
var args=parseList.Zip(令牌,(解析器,值)=>parser(值));
yield return(T)Activator.CreateInstance(typeof(T),args.ToArray());
}
}
私有静态IEnumerable构建解析器(类型t)
{
//现在,我们假设您只有一个公共构造函数。
var ci=t.GetConstructors().First();
foreach(ci.GetParameters()中的var pi)
{
var parser=fetchParseMethod(pi.ParameterType);
Func-boxingParser;
if(解析器!=null)
boxingParser=value=>parser.Invoke(null,新对象[]{value});
其他的
boxingParser=value=>value;
收益率-返回boxingParser;
}
}
私有静态System.Reflection.MethodInfo fetchParseMethod(类型t)
{
返回(来自t.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)中的mi)
设parms=mi.GetParameters()
其中mi.Name==“Parse”&&parms.Length==1&&parms.First()。ParameterType==typeof(String)
选择mi.FirstOrDefault();
}
然后使用如下代码:
Name One, 123, 13.88, 12.25
Name Two, 321, 12.56, 10.75
foreach(var stuff in Extract<Struff>(@"C:\blah.txt"))
{
// Do something with stuff
}
foreach(摘录中的var内容(@“C:\blah.txt”))
{
//用东西做点什么
}
简要概述
这看起来可能有点难以接受。。。但其实很简单:
Stuff
)ParameterType
,并获取它的Parse()
方法Parse()
方法将其转换为对象
Stuff
)虽然这对你来说可能太过分了。。。我在创作它的时候玩得很开心,希望我们都能从中学习到一些东西。此外,此解决方案非常灵活。如果您稍后向构造函数添加参数,这将自动拾取它。您尝试了什么?你到底被困在哪里?你知道如何打开/读取文件吗?需要帮助分析字符串吗?请具体说明。在C#中可以找到数百个读取/解析文本文件的示例。你试过什么吗?我不知道该怎么做。我希望能够逐行读取文件,并将其放入自定义类的on对象中,以便将文件中的测试按以下顺序放入数组:string、int、decimal、double。我是一个初学者,不知道该怎么做。我找到了一些例子,但它们似乎总是针对同一类型。如果我把它放进一个字符串数组,我没有问题,但是我需要数组接受不同的类型谢谢你的帮助(填鸭式回答“给我代码”的问题让我觉得这个解决方案的一个问题是
ReadAllLines()
。如果文本文件太大怎么办?没有理由不使用ReadLines()
…您已经在使用foreach()
。在这种情况下,我不能使用列表。您有其他选择吗?使用纯数组,用行实例化它。长度
,然后将foreach
替换为for(int I=0;
。。。