2011-03-01 142 views
0

我有一個關於繼承問題,所以我將描述如下情況:繼承和多重構造

我讀包含日誌的文本文件。 (每行一個日誌) 每個日誌線將具有以下格式: 「日期類型描述」

然而,根據日誌的「類型」,我將不得不解析「說明」不同,拉出不同的領域。

下面是一些例子:

5/1/2011 Information Field1, Field2, Field3 
5/2/2011 Error  Field1 

- 所以,我試圖做的是這樣的:
- 獲得一個線路輸出日誌
的-Parse根據圖案爲「日期類型說明」
-Look在‘類型’字段,並創建新的對象/解析需要說明

public class Log 
{ 
    public DateTime Date; 
    public String Type; 
    public String Description; 

    public Log(String line) 
    { 
     this.Date = GetDate(); 
     this.Type = GetType(); 
     this.Description = GetDescription(); 
    } 
} 

public class InformationLog : Log 
{ 
    public String Field1; 
    public String Field2; 
    public String Field3; 

    public InformationLog(Log log) 
    { 
     this.Field1 = GetField1(log.Description); 
     this.Field1 = GetField2(log.Description); 
     this.Field1 = GetField3(log.Description); 
    } 
} 

public class Client 
{ 
    public void Main() 
    { 
     String line = ReadFileAndGetLine(); // Get a line from the file 
     Log log = new Log(line); 
     if(log.Type == "Information") 
      log = new InformationLog(log); // Is this right? 
    } 
} 

這是我想要的方式,但似乎這不是一個好習慣。 「log」變量將自身用作其自己的構造函數的參數。

我的問題是: 有沒有這樣做的標準方式?或者,這個實施有什麼問題嗎?

-
編輯:
另外,我應該提到:我的理由是,我會分析行一次走出日期和類型,然後再分析它,以獲得更精細的細節。
我決定使用繼承,所以我不必解析出Date和Type字段兩次。

+1

爲什麼不只是使用'Log'來做條件分析呢? – 2011-03-01 14:22:02

+0

@Mr。失望:每種類型的日誌都有不同的參數,所以我不想把「Field1,Field2,Field3等」如果它們不是必需的,則記錄在「日誌」中。 – Eric 2011-03-01 14:24:41

+1

讚賞,但如果它們總是包含'Type'和'Description',那麼這仍然可以發生在基類中。 – 2011-03-01 14:27:33

回答

2

按我的意見,爲什麼不只是做一些有點像這樣:

public enum LogEntryType 
    { 
     Error = -1, 
     Information = 0, 
    } 

    public class LogEntry 
    { 
     public string Raw; 
     public DateTime Date; 
     public LogEntryType Type; 
     public string Description; 

     public LogEntry(String line) 
     { 
      Raw = line; 
      Date = ParseDate(); 
      Type = ParseType(); 
      Description = ParseDescription(); 
     } 

     public string ParseDescription() 
     { 
      var result = string.Empty; 
      switch(Type) 
      { 
       case LogEntryType.Error: 
        //parse here 
        break; 
       case LogEntryType.Information: 
        //parse here 
        break; 
      } 
      return result; 
     } 
    } 

我注意你在派生類中有字段,但是可以在這裏解釋描述;不過,我可以看到爲什麼人們可能想要將它轉移到實際上知道的地方如何解析描述,在這種情況下,您可以使用在另一個答案中建議的工廠模式,或者實現「屬性包」類型場景 - 但我認爲,這些日子裏,強烈的打字習慣會逐漸消失。

另一個建議雖然與初次嘗試非常相似,但傾向於封裝類型的管理,而不是讓分離的類處理這些東西 - 一種模式(表面上),如Exception,其中有一個根條目,內部條目:

public enum LogEntryType 
    { 
     Error = -1, 
     Information = 0, 
    } 

    public class LogEntry 
    { 
     public string Raw; 
     public DateTime Date; 
     public LogEntryType Type; 
     public string Description; 

     public InnerLogEntry InnerEntry; 

     public LogEntry(String line) 
     { 
      Raw = line; 
      Date = ParseDate(); 
      Type = ParseType(); 
      //parse the 'raw' description... 
      Description = ParseDescription(); 
      //determine the inner entry type... 
      switch (Type) 
      { 
       case LogEntryType.Error: 
        InnerEntry = new ErrorLogEntry(this); 
        break; 
       case LogEntryType.Information: 
        InnerEntry = new InformationLogEntry(this); 
        break; 
      }     
     } 
    } 

    public abstract class InnerLogEntry 
    { 
     protected LogEntry Parent; 

     public InnerLogEntry(LogEntry logEntry) 
     { 
      Parent = logEntry; 
     } 
    } 

    public class InformationLogEntry : InnerLogEntry 
    { 
     public InformationLogEntry(LogEntry logEntry) 
      : base(logEntry) 
     { 
      //parse custom data 
     } 
    } 

    public class ErrorLogEntry : InnerLogEntry 
    { 
     public ErrorLogEntry(LogEntry logEntry) 
      : base(logEntry) 
     { 
      //parse custom data 
     } 
    } 
+0

謝謝,但是,我看不出如何去存儲「Field1,Field2等」。參數? - 「說明」可能包含3個字符串,或者可能有DateTime和Double等。 – Eric 2011-03-01 14:28:55

+0

我喜歡你的第二次嘗試。對我來說,其實看起來像一個抽象工廠。我認爲這是我想要進入的更多方向,謝謝。 – Eric 2011-03-01 14:48:13

+0

沒問題,我認爲它比某些情況更適合 - 特別是如果它適合你的話。你也可以從'LogEntry'派生'InnerLogEntry',這樣每個條目都可以有一組基本的數據和/或他們自己的孩子 - 這需要更多的調整,但這只是一個想法。 – 2011-03-01 14:52:36

4

嘗試使用Factory pattern

static class LogFactory 
{ 
    public static Log Create(String line) 
    { 
     if(GetType(line) == "Information") 
      return CreateInformationLog(line); 
     return CreateLog(line); 
    } 

    private static Log CreateLog(String line) 
    { 
     return new Log(line); 
    } 

    private static Log CreateInformationLog(String line) 
    { 
     return new InformationLog(line); 
    } 
} 

,然後嘗試用

String line = ReadFileAndGetLine(); // Get a line from the file 
    Log log = LogFactory.Create(line); 
+0

謝謝。有沒有辦法保留字段「日期」和「類型」而不必調用「GetType(line)」兩次?看起來InformationLog(line)的構造函數將不得不再次調用GetType(line)。 – Eric 2011-03-01 14:34:54

+0

然後你可以擴展構造函數到'日誌(字符串行,字符串類型)' – Stecya 2011-03-01 14:50:09