mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-04-29 11:34:13 +02:00
Remove unknown property error in FileSerializer & refactor reading
This commit is contained in:
parent
b8aae88b11
commit
e51e87647e
Configuration
Core/Other/Analytics
Data/Serialization
@ -4,9 +4,7 @@
|
|||||||
|
|
||||||
namespace TweetDuck.Configuration{
|
namespace TweetDuck.Configuration{
|
||||||
sealed class SystemConfig{
|
sealed class SystemConfig{
|
||||||
private static readonly FileSerializer<SystemConfig> Serializer = new FileSerializer<SystemConfig>{
|
private static readonly FileSerializer<SystemConfig> Serializer = new FileSerializer<SystemConfig>();
|
||||||
HandleUnknownProperties = FileSerializer<SystemConfig>.IgnoreProperties("EnableBrowserGCReload", "BrowserMemoryThreshold")
|
|
||||||
};
|
|
||||||
|
|
||||||
public static readonly bool IsHardwareAccelerationSupported = File.Exists(Path.Combine(Program.ProgramPath, "libEGL.dll")) &&
|
public static readonly bool IsHardwareAccelerationSupported = File.Exists(Path.Combine(Program.ProgramPath, "libEGL.dll")) &&
|
||||||
File.Exists(Path.Combine(Program.ProgramPath, "libGLESv2.dll"));
|
File.Exists(Path.Combine(Program.ProgramPath, "libGLESv2.dll"));
|
||||||
|
@ -11,9 +11,7 @@
|
|||||||
|
|
||||||
namespace TweetDuck.Configuration{
|
namespace TweetDuck.Configuration{
|
||||||
sealed class UserConfig{
|
sealed class UserConfig{
|
||||||
private static readonly FileSerializer<UserConfig> Serializer = new FileSerializer<UserConfig>{
|
private static readonly FileSerializer<UserConfig> Serializer = new FileSerializer<UserConfig>();
|
||||||
HandleUnknownProperties = FileSerializer<UserConfig>.IgnoreProperties("AppLocale", "ShowDataCollectionNotification")
|
|
||||||
};
|
|
||||||
|
|
||||||
static UserConfig(){
|
static UserConfig(){
|
||||||
Serializer.RegisterTypeConverter(typeof(WindowState), WindowState.Converter);
|
Serializer.RegisterTypeConverter(typeof(WindowState), WindowState.Converter);
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
|
|
||||||
namespace TweetDuck.Core.Other.Analytics{
|
namespace TweetDuck.Core.Other.Analytics{
|
||||||
sealed class AnalyticsFile{
|
sealed class AnalyticsFile{
|
||||||
private static readonly FileSerializer<AnalyticsFile> Serializer = new FileSerializer<AnalyticsFile>{
|
private static readonly FileSerializer<AnalyticsFile> Serializer = new FileSerializer<AnalyticsFile>();
|
||||||
HandleUnknownProperties = FileSerializer<AnalyticsFile>.IgnoreProperties("CountGCReloads")
|
|
||||||
};
|
|
||||||
|
|
||||||
static AnalyticsFile(){
|
static AnalyticsFile(){
|
||||||
Serializer.RegisterTypeConverter(typeof(DateTime), new SingleTypeConverter<DateTime>{
|
Serializer.RegisterTypeConverter(typeof(DateTime), new SingleTypeConverter<DateTime>{
|
||||||
|
@ -52,9 +52,6 @@ private static string UnescapeStream(StreamReader reader){
|
|||||||
|
|
||||||
private static readonly ITypeConverter BasicSerializerObj = new BasicTypeConverter();
|
private static readonly ITypeConverter BasicSerializerObj = new BasicTypeConverter();
|
||||||
|
|
||||||
public delegate void HandleUnknownPropertiesHandler(T obj, Dictionary<string, string> data);
|
|
||||||
public HandleUnknownPropertiesHandler HandleUnknownProperties { get; set; }
|
|
||||||
|
|
||||||
private readonly Dictionary<string, PropertyInfo> props;
|
private readonly Dictionary<string, PropertyInfo> props;
|
||||||
private readonly Dictionary<Type, ITypeConverter> converters;
|
private readonly Dictionary<Type, ITypeConverter> converters;
|
||||||
|
|
||||||
@ -93,71 +90,60 @@ public void Write(string file, T obj){
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Read(string file, T obj){
|
public void Read(string file, T obj){
|
||||||
Dictionary<string, string> unknownProperties = new Dictionary<string, string>(4);
|
string contents;
|
||||||
|
|
||||||
using(StreamReader reader = new StreamReader(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))){
|
using(StreamReader reader = new StreamReader(new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))){
|
||||||
switch(reader.Peek()){
|
contents = UnescapeStream(reader);
|
||||||
case -1:
|
}
|
||||||
throw new FormatException("File is empty.");
|
|
||||||
case 0:
|
if (string.IsNullOrWhiteSpace(contents)){
|
||||||
case 1:
|
throw new FormatException("File is empty.");
|
||||||
throw new FormatException("Input appears to be a binary file.");
|
}
|
||||||
|
else if (contents[0] <= (char)1){
|
||||||
|
throw new FormatException("Input appears to be a binary file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int currentPos = 0;
|
||||||
|
|
||||||
|
do{
|
||||||
|
string line;
|
||||||
|
int nextPos = contents.IndexOf(NewLineReal, currentPos);
|
||||||
|
|
||||||
|
if (nextPos == -1){
|
||||||
|
line = contents.Substring(currentPos);
|
||||||
|
currentPos = -1;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(line)){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
line = contents.Substring(currentPos, nextPos-currentPos);
|
||||||
|
currentPos = nextPos+NewLineReal.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
string contents = UnescapeStream(reader);
|
|
||||||
int currentPos = 0;
|
|
||||||
|
|
||||||
do{
|
|
||||||
string line;
|
|
||||||
int nextPos = contents.IndexOf(NewLineReal, currentPos);
|
|
||||||
|
|
||||||
if (nextPos == -1){
|
|
||||||
line = contents.Substring(currentPos);
|
|
||||||
currentPos = -1;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(line)){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
line = contents.Substring(currentPos, nextPos-currentPos);
|
|
||||||
currentPos = nextPos+NewLineReal.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
int space = line.IndexOf(' ');
|
int space = line.IndexOf(' ');
|
||||||
|
|
||||||
if (space == -1){
|
if (space == -1){
|
||||||
throw new SerializationException($"Invalid file format, missing separator: {line}");
|
throw new SerializationException($"Invalid file format, missing separator: {line}");
|
||||||
|
}
|
||||||
|
|
||||||
|
string property = line.Substring(0, space);
|
||||||
|
string value = UnescapeLine(line.Substring(space+1));
|
||||||
|
|
||||||
|
if (props.TryGetValue(property, out PropertyInfo info)){
|
||||||
|
if (!converters.TryGetValue(info.PropertyType, out ITypeConverter serializer)){
|
||||||
|
serializer = BasicSerializerObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
string property = line.Substring(0, space);
|
if (serializer.TryReadType(info.PropertyType, value, out object converted)){
|
||||||
string value = UnescapeLine(line.Substring(space+1));
|
info.SetValue(obj, converted);
|
||||||
|
|
||||||
if (props.TryGetValue(property, out PropertyInfo info)){
|
|
||||||
if (!converters.TryGetValue(info.PropertyType, out ITypeConverter serializer)){
|
|
||||||
serializer = BasicSerializerObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serializer.TryReadType(info.PropertyType, value, out object converted)){
|
|
||||||
info.SetValue(obj, converted);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
throw new SerializationException($"Invalid file format, cannot convert value: {value} (property: {property})");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
unknownProperties[property] = value;
|
throw new SerializationException($"Invalid file format, cannot convert value: {value} (property: {property})");
|
||||||
}
|
}
|
||||||
}while(currentPos != -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unknownProperties.Count > 0){
|
|
||||||
HandleUnknownProperties?.Invoke(obj, unknownProperties);
|
|
||||||
|
|
||||||
if (unknownProperties.Count > 0){
|
|
||||||
throw new SerializationException($"Invalid file format, unknown properties: {string.Join(", ", unknownProperties.Keys)}");
|
|
||||||
}
|
}
|
||||||
}
|
}while(currentPos != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReadIfExists(string file, T obj){
|
public void ReadIfExists(string file, T obj){
|
||||||
@ -167,14 +153,6 @@ public void ReadIfExists(string file, T obj){
|
|||||||
}catch(DirectoryNotFoundException){}
|
}catch(DirectoryNotFoundException){}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HandleUnknownPropertiesHandler IgnoreProperties(params string[] properties){
|
|
||||||
return (obj, data) => {
|
|
||||||
foreach(string property in properties){
|
|
||||||
data.Remove(property);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class BasicTypeConverter : ITypeConverter{
|
private sealed class BasicTypeConverter : ITypeConverter{
|
||||||
bool ITypeConverter.TryWriteType(Type type, object value, out string converted){
|
bool ITypeConverter.TryWriteType(Type type, object value, out string converted){
|
||||||
switch(Type.GetTypeCode(type)){
|
switch(Type.GetTypeCode(type)){
|
||||||
|
Loading…
Reference in New Issue
Block a user