目前我在strings
中有很多array
可以填充所有类型的数据。一个例子:
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
数组中填充了不同的字符串,其中包含外部数据(例如,来自obj
和test
对象的数据)。
我的问题:
目标是从text
读取.txt file
行并将其加载到text
变量中,因此结果将与上面相同。
唯一的条件是此文本文件必须包含所有'变量',如obj
和test.title
,因此它将打印这些对象中包含的正确数据。如何将这些行存储在.txt file
中并将它们加载到应用程序中?
答案 0 :(得分:1)
您将需要创建占位符
在文件中将有行:
${obj} contains ${obj.attribute}
This is a ${test.title}"
占位符是$ {....}
然后你需要逐行解析文件。
您解决占位符。
在占位符中,字符串的第一部分是对象的名称。
因此,您需要在程序中将对象存在的对象存入文件中的对象。
然后,使用该映射器创建容器
然后,您将对象从文件映射到容器中的对象,并使用反射获得您在占位符中定义的内容的值
另一种方式:
您只有占位符和映射器。
在档案中:
${obj} contains ${obj.attribute}
This is a ${test.title}"
Mapper(例如字典)
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;
}
}
答案 1 :(得分: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; }
}
}
答案 2 :(得分: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);
}