2016-01-20 80 views
0

目前我有很多stringsarray可以填充各種數據。一個例子:從模板文件加載文本

var obj = new Example();  
var test = new Test(); 

// This must be stored in a text file 
var text = new[] { 
    $"{obj} contains {obj.attribute}", 
    $"This is a {test.title}" 
} 

foreach (var line in text) 
    Console.WriteLine(line); 

正如所看到的,這個text陣列填充有不同的字符串,其包含外部數據(例如,數據從objtest對象)。


我的問題: 的目標是從.txt file讀取的text行,並將它們加載到text變量,所以結果將是相同的如上述。

唯一的條件是該文本文件必須包含所有'變量',如objtest.title,因此它將打印這些對象中包含的正確數據。如何將這些行存儲在.txt file中並將它們加載到應用程序中?

+1

這不是我清楚你要完成的任務。或者字符串數組現在看起來是什麼樣子,讀完文件後應該是什麼樣子。此外,你應該知道,文件I/O是一個相當廣泛的主題,所以你應該有一個_specific_問題,而不是「這是做什麼最好的方法」 – ryanyuyu

+0

@ryanyuyu我試圖改善這個問題,希望它現在很清楚 –

+0

您是否需要字面字符串'「{obj}」'或者您是否實際上必須解析文本文件並獲取「obj」實際上的值?目前尚不清楚。有很多更好的方式來存儲數據在文件中。 XML是存儲數據的一種體面的可讀方式。 – ryanyuyu

回答

0

基於mnieto的答案我已經能夠建立一個實際的解決我的問題:

public class TemplateParser 
{ 
    private string _content; 
    public Dictionary<string, object> Variables { get; } = new Dictionary<string, object>(); 

    public TemplateParser(string filepath) 
    { 
     try 
     { 
      _content = File.ReadAllText(filepath); 
     } 
     catch (IOException) 
     { 
      Console.WriteLine("File could not be found on the following location:\n" + filepath); 
     } 
    } 

    public void Parse() 
    { 
     var placeholder = ""; 
     var beginIndex = 0; 
     var busy = false; 

     for (var i = 0; i < _content.Length; i++) 
      switch (_content[i]) 
      { 
       case '{': 
        placeholder = ""; 
        busy = true; 
        beginIndex = i; 

        break; 
       case '}': 
        if (placeholder != "") 
        { 
         var position = placeholder.IndexOf('.'); 
         var success = false; 

         try 
         { 
          object pValue; 
          if (position >= 0) 
          { 
           var pName = placeholder.Substring(position + 1); 
           pValue = GetPropertyValue(Variables[placeholder.Substring(0, position)], pName); 
          } 
          else pValue = Variables[placeholder]; 

          if (pValue == null) 
          { 
           Console.WriteLine("Property not found"); 
           throw new KeyNotFoundException("Property not found"); 
          } 

          _content = _content.Replace("{" + placeholder + "}", pValue.ToString()); 
          success = true; 
         } 
         catch (KeyNotFoundException) 
         { 
          Console.WriteLine("WARNING: Placeholder {" + placeholder + "} is unknown"); 
          _content = _content.Replace("{" + placeholder + "}", "x"); 
         } 

         busy = false; 
         if (success) i = beginIndex; 
        } 

        break; 
       default: 
        if (busy) placeholder += _content[i]; 
        break; 
      } 
    } 

    private static object GetPropertyValue(object obj, string propertyName) 
    { 
     var pi = obj.GetType().GetProperties().FirstOrDefault(x => x.Name == propertyName); 

     FieldInfo fi = null; 
     if (pi == null) 
      foreach (var x in obj.GetType().GetFields().Where(x => x.Name == propertyName)) 
      { 
       fi = x; 
       break; 
      } 

     return pi != null ? pi.GetValue(obj) : fi?.GetValue(obj); 
    } 

    public string[] ToArray() => _content.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries); 
} 
1

您將NEDD創建佔位符

在文件將有行:

${obj} contains ${obj.attribute} 
This is a ${test.title}" 

佔位符$ {....}

,那麼你將需要解析的文件,一行行。

您解決佔位符。

在佔位符字符串的第一部分是對象的名稱。

因此,您需要在程序中將現有對象的映射器映射到文件中。

然後,你與映射

那麼你是映射從文件的對象從容器中,並使用反射來反對你得到了什麼你在佔位符定義

另一種方式谷創建容器:

您只有佔位符和映射器。

在文件:

${obj} contains ${obj.attribute} 
    This is a ${test.title}" 

映射器(例如字典)

var fileMapper = new Dictionary<string, string> 
        { 
         ["obj"] = "sfsfs", 
         ["obj.attribute"] = "sfsfs" 
        }; 

,現在你需要得到佔位符,並與對象的形式字典更換。

反射是不nessesery

全部工作實施例(編譯和測試)

class Example 
    { 
     public void GetFile() 
     { 
      var fileMapper = new Dictionary<string, string> 
      { 
       ["obj"] = "sfsfs", 
       ["obj.attribute"] = "sfsfs" 
      }; 

      var fileLines = new List<string>(); 

      using (var sr = new StreamReader("FileName")) 
      { 
       var line = string.Empty; 

       while ((line = sr.ReadLine()) != null) 
       { 
        List<string> listOfPlaceHolders = this.GetPlaceHolders(line); 

        for (var i = 0; i < listOfPlaceHolders.Count; i++) 
        { 
         line = line.Replace("${" + listOfPlaceHolders[i] + "}", fileMapper[listOfPlaceHolders[i]]); 
        } 

        fileLines.Add(line); 
       } 
      } 


      foreach (var line in fileLines) 
      { 
       Console.WriteLine(line); 
      } 
     } 

     public List<string> GetPlaceHolders(string line) 
     { 
      var result = new List<string>(); 

      var placeHoldersIndex = new List<int>(); 

      var open = false; 

      for (var i = 0; i < line.Length; i++) 
      { 
       if (line[i] == '{' && !open) 
       { 
        open = true; 
        placeHoldersIndex.Add(i+1); 
       } 

       if (line[i] == '}' && open) 
       { 
        placeHoldersIndex.Add(i); 
        open = false; 
       } 
      } 

      for (var j = 0; j < placeHoldersIndex.Count(); j += 2) 
      { 
       result.Add(line.Substring(placeHoldersIndex[j], placeHoldersIndex[j+1] - placeHoldersIndex[j])); 
      }; 

      return result; 
     } 

    } 
+0

你能舉個例子嗎? –

+0

您在這裏:) –

1

這裏是一個可能的解決方案(編譯,但是未測試):

聲明等一類這個:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Reflection; 
using System.Text; 


namespace ConsoleApplication1 { 
    public class TemplateParser { 

     private string content; 

     public TemplateParser(string fileName) { 
      Tags = new Dictionary<string, object>(); 
      //TODO: Add exception control. Perhaps move the reading operation outside the constructor 
      content = File.ReadAllText(fileName); 
     } 

     public Dictionary<string, object> Tags { get; private set; } 

     public void Parse() { 
      foreach (string key in Tags.Keys) { 
       if (Tags[key] != null) { 
       object propertyValue; 
       int position = key.IndexOf('.'); 
       if (position >= 0) { 
        string propertyName = key.Substring(position + 1); 
        propertyValue = GetPropertyValue(Tags[key], propertyName); 
       } else { 
        propertyValue = Tags[key]; 
       } 
       content = content.Replace(string.Concat("{", key, "}"), propertyValue.ToString()); 
       } else { 
        //TODO: what to do without not specified replacement? 
       } 
      } 
     } 

     public string[] ToArray() { 
      return content.Split(new string[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries); 
     } 


     private object GetPropertyValue(object obj, string propertyName) { 
      PropertyInfo pi = obj.GetType().GetProperties().FirstOrDefault(x => x.Name == propertyName); 
      if (pi != null) { 
       return pi.GetValue(obj, null); 
      } 
      return null; 
     } 

    } 
} 

用法:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace ConsoleApplication1 { 
    class Program { 
     static void Main(string[] args) { 
      TemplateParser parser = new TemplateParser("C:\\myTextFile.txt"); 
      parser.Tags.Add("obj", 1); 
      parser.Tags.Add("Test", new Test { Id = 1, Title = "This is a text" }); 

      parser.Parse(); 
      foreach (string line in parser.ToArray()) { 
       Console.WriteLine(line); 
      } 
     } 
    } 

    class Test { 
     public int Id { get; set; } 
     public string Title { get; set; } 
    } 
} 
+0

偉大的解決方案,只有'替換'只適用於沒有財產 –