我有一个问题,我不知道如何解决,我希望这里的人能提供一些好的建议。
我正在解析文本文件,其中包含多个日志(每行一个日志)。格式如下:
Date Type Description
10/20 A LogTypeADescription
10/20 B LogTypeBDescription
10/20 C LogTypeCDescription
在这里,您可以看到日志有三种“类型”(A、B 和 C)。根据日志的类型,我将以不同的方式解析“Description”字段。
我的问题是我应该如何设置数据结构?
我想做这样的事情:
class Log
{
DateTime Date;
String Type;
String Description;
public Log(String line)
{
Parse(line);
}
}
class ALog : Log { }
class BLog : Log { }
class CLog : Log { }
现在,每个派生类都可以有自己独特的属性,具体取决于“描述”字段的解析方式,并且它们仍将维护三个“核心”属性(日期、类型和描述) )。
到目前为止一切都很好,除了在解析日志文件中的行之前我不知道我需要什么类型的(派生)日志。当然,我可以解析该行,然后弄清楚它,但我真的希望解析代码位于“Log”构造函数中。我希望我能做这样的事情:
void Parse(String line)
{
String[] pieces = line.Split(' ');
this.Date = DateTime.Parse(pieces[0]);
this.Type = pieces[1];
this.Description = pieces[2];
if(this.Type == "A")
this = new ALog();
else if(this.Type == "B")
this = new BLog();
else if(this.Type == "C")
this = new CLog();
}
但不幸的是我认为这是不可能的。
我还没有尝试过,但我很确定这样做:
Log l = new Log(line);
if(l.Type == "A") l = new ALog();
要么是非法的,要么会破坏我第一次创建“日志”时所做的所有解析。
有什么建议吗?
I have a problem that I'm not sure how to approach, and I'm hoping the people here will have some good tips.
I am parsing text files, which contain several logs (one log per line). The format is something like the following:
Date Type Description
10/20 A LogTypeADescription
10/20 B LogTypeBDescription
10/20 C LogTypeCDescription
Here, you can see there are three "types" of logs (A, B, and C). Depending on what type the log is, I will parse the "Description" field differently.
My question is how should I set up the data structure?
I would like to do something like this:
class Log
{
DateTime Date;
String Type;
String Description;
public Log(String line)
{
Parse(line);
}
}
class ALog : Log { }
class BLog : Log { }
class CLog : Log { }
Now, each derived class can have its own unique properties, depending on how the "Description" field is parsed, and they will still maintain the three "core" properties (Date, Type, and Description).
Everything is good so far, except I don't know what type of (derived) log I need until I have parsed the line from the log file. Of course, I could parse the line, and then figure it out, but I really want the parsing code to be in the "Log" constructor. I wish I could do something like this:
void Parse(String line)
{
String[] pieces = line.Split(' ');
this.Date = DateTime.Parse(pieces[0]);
this.Type = pieces[1];
this.Description = pieces[2];
if(this.Type == "A")
this = new ALog();
else if(this.Type == "B")
this = new BLog();
else if(this.Type == "C")
this = new CLog();
}
But unfortunately I don't think this is possible.
I haven't tried yet, but I'm pretty sure doing this:
Log l = new Log(line);
if(l.Type == "A") l = new ALog();
Would either be illegal or destroy all of the parsing I did when I first created the "Log."
Any suggestions?
发布评论
评论(5)
删除构造函数并将 Parse 更改为返回 Log 的静态。
Remove the constructor and change Parse to a static that returns a Log.
我会将描述解析分解为一个抽象方法,该方法可以针对不同的描述类型进行覆盖。只有描述有所不同,因此只有这部分行解析需要分解为派生类型中包含的逻辑。
I would factor out the description parsing into an abstract method that could be overridden for the different description types. Only the description varies, so only this part of the line parsing needs factored out into logic contained within derived types.
您可以像这样拆分读取该行,然后读取“类型”并调用 Activator 创建从(可能是抽象的)基本日志派生的具体类型之一,将拆分参数传递给创建新的特定具体实例的构造函数。
(此外,“类型”可能是派生类中的只读属性,因为您知道基于实例类型的值)。
当然,假设您不想避免反思。
You could read the line in a split it like you are, then read the "type" and call the Activator to create one of your concrete types derived from your (probably abstract) base log, passing in your split arguments to the constructor creating a new specific concrete instance.
(Also, the "Type" could be a read-only property in your derived classes since you know value based on the instance type).
Of course, assuming you're not wanting to avoid reflection.
还有另一个解决方案。放下你的面向对象锤子,拿起你的功能锤子。
C# 有字典和匿名函数。拥有一个函数字典,该字典知道如何获取
Log
和描述,并可以解析该信息并将其放入Log
中。然后你只需parseDescription[logType](this, description)
。这意味着您需要一个具有 3 个函数的字典,而不是 3 个新类。
在这个例子中差异并没有那么大。但请考虑日志条目中是否有 2 个不同的字段可能需要以多种方式进行解析。基于类的方法需要 9 个新类,而字典方法有 2 个字典,每个字典有 3 个函数。如果有 3 个,则比较将是 27 个类与 3 个字典,每个字典有 3 个函数。
Yet another solution. Put down your OO hammer, and pick up your functional one.
C# has dictionaries and anonymous functions. Have a dictionary of functions that know how to take a
Log
and a description and can parse that information and put it into theLog
. Then you justparseDescription[logType](this, description)
.This means you need a dictionary with 3 functions rather that 3 new classes.
The difference is not so big in this example. But consider if there were 2 different fields in your log entry that might need to be parsed in multiple ways. The class based approach needs 9 new classes while the dictionary approach has 2 dictionaries with 3 functions each. If there were 3 the comparison would be 27 classes versus 3 dictionaries with 3 functions each.
重新审视 joncham 和 btilly 的方法:
A re-take on joncham's and btilly's approaches: