Deserialize code optimisations

1. reading ini files
2. regex match of section names.
This commit is contained in:
Brett Hewitson 2021-12-15 21:31:04 +10:00
parent f73b8c530d
commit 5c06fd00d5
2 changed files with 143 additions and 80 deletions

View file

@ -35,26 +35,35 @@ namespace ServerManagerTool.Common.Serialization
public void Deserialize(object obj, Enum[] exclusions) public void Deserialize(object obj, Enum[] exclusions)
{ {
var iniFiles = new Dictionary<string, IniFile>(); var iniFiles = new Dictionary<string, IniFile>();
var fields = obj.GetType().GetProperties().Where(f => f.IsDefined(typeof(BaseIniFileEntryAttribute), false)); var fields = obj.GetType()
.GetProperties()
.Where(f => f.IsDefined(typeof(BaseIniFileEntryAttribute), false));
if (exclusions == null) if (exclusions == null)
{
exclusions = new Enum[0]; exclusions = new Enum[0];
}
foreach (var field in fields) foreach (var field in fields)
{ {
var attributes = field.GetCustomAttributes(typeof(BaseIniFileEntryAttribute), false); var attributes = field
foreach (var attr in attributes.OfType<BaseIniFileEntryAttribute>()) .GetCustomAttributes(typeof(BaseIniFileEntryAttribute), false)
.OfType<BaseIniFileEntryAttribute>()
.Where(a => !exclusions.Contains(a.Category));
foreach (var attr in attributes)
{ {
if (exclusions.Contains(attr.Category)) if (exclusions.Contains(attr.Category))
{
continue; continue;
}
try try
{ {
if (attr.IsCustom) if (attr.IsCustom)
{ {
// this code is to handle custom sections // this code is to handle custom sections
var collection = field.GetValue(obj) as IIniSectionCollection; if (field.GetValue(obj) is IIniSectionCollection collection)
if (collection != null)
{ {
ReadFile(iniFiles, attr.File); ReadFile(iniFiles, attr.File);
@ -77,11 +86,7 @@ namespace ServerManagerTool.Common.Serialization
} }
else else
{ {
var iniValue = ReadValue(iniFiles, attr.File, attr.Section, keyName); if (field.GetValue(obj) is IIniValuesCollection collection)
var fieldType = field.PropertyType;
var collection = field.GetValue(obj) as IIniValuesCollection;
if (collection != null)
{ {
var section = ReadSection(iniFiles, attr.File, attr.Section); var section = ReadSection(iniFiles, attr.File, attr.Section);
var filteredSection = collection.IsArray var filteredSection = collection.IsArray
@ -89,25 +94,40 @@ namespace ServerManagerTool.Common.Serialization
: section.Where(s => s.StartsWith(collection.IniCollectionKey + "=")); : section.Where(s => s.StartsWith(collection.IniCollectionKey + "="));
collection.FromIniValues(filteredSection); collection.FromIniValues(filteredSection);
} }
else if (fieldType == typeof(string)) else
{
var iniValue = ReadValue(iniFiles, attr.File, attr.Section, keyName);
var fieldType = field.PropertyType;
if (fieldType == typeof(string))
{ {
var stringValue = iniValue; var stringValue = iniValue;
if (attr.QuotedString == QuotedStringType.True) if (attr.QuotedString == QuotedStringType.True)
{ {
// remove the leading and trailing quotes, if any // remove the leading and trailing quotes, if any
if (stringValue.StartsWith("\"")) if (stringValue.StartsWith("\""))
{
stringValue = stringValue.Substring(1); stringValue = stringValue.Substring(1);
}
if (stringValue.EndsWith("\"")) if (stringValue.EndsWith("\""))
{
stringValue = stringValue.Substring(0, stringValue.Length - 1); stringValue = stringValue.Substring(0, stringValue.Length - 1);
} }
}
else if (attr.QuotedString == QuotedStringType.Remove) else if (attr.QuotedString == QuotedStringType.Remove)
{ {
// remove the leading and trailing quotes, if any // remove the leading and trailing quotes, if any
if (stringValue.StartsWith("\"")) if (stringValue.StartsWith("\""))
{
stringValue = stringValue.Substring(1); stringValue = stringValue.Substring(1);
}
if (stringValue.EndsWith("\"")) if (stringValue.EndsWith("\""))
{
stringValue = stringValue.Substring(0, stringValue.Length - 1); stringValue = stringValue.Substring(0, stringValue.Length - 1);
} }
}
if (attr.Multiline) if (attr.Multiline)
{ {
stringValue = stringValue.Replace(attr.MultilineSeparator, Environment.NewLine); stringValue = stringValue.Replace(attr.MultilineSeparator, Environment.NewLine);
@ -131,9 +151,13 @@ namespace ServerManagerTool.Common.Serialization
var valueSet = StringUtils.SetPropertyValue(iniValue, obj, field, attr); var valueSet = StringUtils.SetPropertyValue(iniValue, obj, field, attr);
if (!valueSet) if (!valueSet)
{
throw new ArgumentException($"Unexpected field type {fieldType} for INI key {keyName} in section {attr.Section}."); throw new ArgumentException($"Unexpected field type {fieldType} for INI key {keyName} in section {attr.Section}.");
} }
} }
}
}
} }
} }
catch (Exception) catch (Exception)
@ -147,26 +171,30 @@ namespace ServerManagerTool.Common.Serialization
public void Serialize(object obj, Enum[] exclusions) public void Serialize(object obj, Enum[] exclusions)
{ {
var iniFiles = new Dictionary<string, IniFile>(); var iniFiles = new Dictionary<string, IniFile>();
var fields = obj.GetType().GetProperties().Where(f => f.IsDefined(typeof(BaseIniFileEntryAttribute), false)); var fields = obj.GetType()
.GetProperties()
.Where(f => f.IsDefined(typeof(BaseIniFileEntryAttribute), false));
if (exclusions == null) if (exclusions == null)
{
exclusions = new Enum[0]; exclusions = new Enum[0];
}
foreach (var field in fields) foreach (var field in fields)
{ {
var attributes = field.GetCustomAttributes(typeof(BaseIniFileEntryAttribute), false).OfType<BaseIniFileEntryAttribute>(); var attributes = field
.GetCustomAttributes(typeof(BaseIniFileEntryAttribute), false)
.OfType<BaseIniFileEntryAttribute>()
.Where(a => !exclusions.Contains(a.Category));
foreach (var attr in attributes) foreach (var attr in attributes)
{ {
if (exclusions.Contains(attr.Category))
continue;
try try
{ {
if (attr.IsCustom) if (attr.IsCustom)
{ {
// this code is to handle custom sections // this code is to handle custom sections
var collection = field.GetValue(obj) as IIniSectionCollection; if (field.GetValue(obj) is IIniSectionCollection collection)
if (collection != null)
{ {
collection.Update(); collection.Update();
@ -372,15 +400,20 @@ namespace ServerManagerTool.Common.Serialization
public void WriteSection(Enum iniFile, string sectionName, string[] values) public void WriteSection(Enum iniFile, string sectionName, string[] values)
{ {
var file = Path.Combine(this.BasePath, FileNames[iniFile]); var file = Path.Combine(this.BasePath, FileNames[iniFile]);
var result = IniFileUtils.WriteSection(file, sectionName, values); IniFileUtils.WriteSection(file, sectionName, values);
} }
private string[] ReadCustomSectionNames(Dictionary<string, IniFile> iniFiles, Enum iniFile) private string[] ReadCustomSectionNames(Dictionary<string, IniFile> iniFiles, Enum iniFile)
{
if (!iniFiles.ContainsKey(FileNames[iniFile]))
{ {
ReadFile(iniFiles, iniFile); ReadFile(iniFiles, iniFile);
if (!iniFiles.ContainsKey(FileNames[iniFile])) if (!iniFiles.ContainsKey(FileNames[iniFile]))
{
return new string[0]; return new string[0];
}
}
return iniFiles[FileNames[iniFile]].Sections.Select(s => s.SectionName).Where(s => !SectionNames.ContainsValue(s)).ToArray(); return iniFiles[FileNames[iniFile]].Sections.Select(s => s.SectionName).Where(s => !SectionNames.ContainsValue(s)).ToArray();
} }
@ -391,21 +424,31 @@ namespace ServerManagerTool.Common.Serialization
} }
private string[] ReadSection(Dictionary<string, IniFile> iniFiles, Enum iniFile, string sectionName) private string[] ReadSection(Dictionary<string, IniFile> iniFiles, Enum iniFile, string sectionName)
{
if (!iniFiles.ContainsKey(FileNames[iniFile]))
{ {
ReadFile(iniFiles, iniFile); ReadFile(iniFiles, iniFile);
if (!iniFiles.ContainsKey(FileNames[iniFile])) if (!iniFiles.ContainsKey(FileNames[iniFile]))
{
return new string[0]; return new string[0];
}
}
return iniFiles[FileNames[iniFile]].GetSection(sectionName)?.KeysToStringArray() ?? new string[0]; return iniFiles[FileNames[iniFile]].GetSection(sectionName)?.KeysToStringArray() ?? new string[0];
} }
private string ReadValue(Dictionary<string, IniFile> iniFiles, Enum iniFile, Enum section, string keyName) private string ReadValue(Dictionary<string, IniFile> iniFiles, Enum iniFile, Enum section, string keyName)
{
if (!iniFiles.ContainsKey(FileNames[iniFile]))
{ {
ReadFile(iniFiles, iniFile); ReadFile(iniFiles, iniFile);
if (!iniFiles.ContainsKey(FileNames[iniFile])) if (!iniFiles.ContainsKey(FileNames[iniFile]))
{
return string.Empty; return string.Empty;
}
}
return iniFiles[FileNames[iniFile]].GetKey(SectionNames[section], keyName)?.KeyValue ?? string.Empty; return iniFiles[FileNames[iniFile]].GetKey(SectionNames[section], keyName)?.KeyValue ?? string.Empty;
} }
@ -416,11 +459,16 @@ namespace ServerManagerTool.Common.Serialization
} }
private void WriteSection(Dictionary<string, IniFile> iniFiles, Enum iniFile, string sectionName, string[] values) private void WriteSection(Dictionary<string, IniFile> iniFiles, Enum iniFile, string sectionName, string[] values)
{
if (!iniFiles.ContainsKey(FileNames[iniFile]))
{ {
ReadFile(iniFiles, iniFile); ReadFile(iniFiles, iniFile);
if (!iniFiles.ContainsKey(FileNames[iniFile])) if (!iniFiles.ContainsKey(FileNames[iniFile]))
{
return; return;
}
}
iniFiles[FileNames[iniFile]].WriteSection(sectionName, values); iniFiles[FileNames[iniFile]].WriteSection(sectionName, values);
} }
@ -431,11 +479,16 @@ namespace ServerManagerTool.Common.Serialization
} }
private void WriteValue(Dictionary<string, IniFile> iniFiles, Enum iniFile, string sectionName, string keyName, string keyValue) private void WriteValue(Dictionary<string, IniFile> iniFiles, Enum iniFile, string sectionName, string keyName, string keyValue)
{
if (!iniFiles.ContainsKey(FileNames[iniFile]))
{ {
ReadFile(iniFiles, iniFile); ReadFile(iniFiles, iniFile);
if (!iniFiles.ContainsKey(FileNames[iniFile])) if (!iniFiles.ContainsKey(FileNames[iniFile]))
{
return; return;
}
}
iniFiles[FileNames[iniFile]].WriteKey(sectionName, keyName, keyValue); iniFiles[FileNames[iniFile]].WriteKey(sectionName, keyName, keyValue);
} }
@ -454,7 +507,7 @@ namespace ServerManagerTool.Common.Serialization
foreach (var iniFile in iniFiles) foreach (var iniFile in iniFiles)
{ {
var file = Path.Combine(this.BasePath, iniFile.Key); var file = Path.Combine(this.BasePath, iniFile.Key);
var result = IniFileUtils.SaveToFile(file, iniFile.Value); IniFileUtils.SaveToFile(file, iniFile.Value);
} }
} }
} }

View file

@ -85,10 +85,14 @@ namespace ServerManagerTool.Common.Utils
public static IniFile ReadFromFile(string file) public static IniFile ReadFromFile(string file)
{ {
if (string.IsNullOrWhiteSpace(file)) if (string.IsNullOrWhiteSpace(file))
{
return null; return null;
}
if (!File.Exists(file)) if (!File.Exists(file))
{
return new IniFile(); return new IniFile();
}
var iniFile = new IniFile(); var iniFile = new IniFile();
@ -96,19 +100,25 @@ namespace ServerManagerTool.Common.Utils
{ {
while (!reader.EndOfStream) while (!reader.EndOfStream)
{ {
var line = reader.ReadLine(); var line = reader.ReadLine().Trim();
if (string.IsNullOrWhiteSpace(line) || line.StartsWith(";") || line.StartsWith("#")) if (string.IsNullOrWhiteSpace(line) || line.StartsWith(";") || line.StartsWith("#"))
{
continue; continue;
}
var sectionName = Regex.Match(line, @"(?<=^\[).*(?=\]$)").Value.Trim(); var sectionName = string.Empty;
if (line.StartsWith("[") && line.EndsWith("]"))
{
sectionName = Regex.Match(line, @"(?<=^\[).*(?=\]$)").Value.Trim();
}
var section = iniFile.AddSection(sectionName); var section = iniFile.AddSection(sectionName);
if (section != null) if (section is null)
continue; {
iniFile.AddKey(line); iniFile.AddKey(line);
} }
}
reader.Close(); reader.Close();
} }