Roblox-File-Format/XmlFormat/XmlPropertyTokens.cs

118 lines
3.5 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using System.Reflection;
using System.ComponentModel;
using System.Linq;
using System.Xml;
2021-02-25 20:09:54 +00:00
using RobloxFiles.Tokens;
namespace RobloxFiles.XmlFormat
{
public static class XmlPropertyTokens
{
2020-08-14 17:35:27 +00:00
private static readonly Dictionary<string, IXmlPropertyToken> Handlers = new Dictionary<string, IXmlPropertyToken>();
static XmlPropertyTokens()
{
// Initialize the PropertyToken handler singletons.
Type IXmlPropertyToken = typeof(IXmlPropertyToken);
var assembly = Assembly.GetExecutingAssembly();
var handlerTypes = assembly.GetTypes()
.Where(type => IXmlPropertyToken.IsAssignableFrom(type))
.Where(type => type != IXmlPropertyToken);
var propTokens = handlerTypes
.Select(handlerType => Activator.CreateInstance(handlerType))
.Cast<IXmlPropertyToken>();
foreach (IXmlPropertyToken propToken in propTokens)
{
2021-02-25 20:09:54 +00:00
var tokens = propToken.XmlPropertyToken.Split(';')
.Select(token => token.Trim())
.ToList();
2020-08-14 17:35:27 +00:00
tokens.ForEach(token => Handlers.Add(token, propToken));
}
}
public static bool ReadPropertyGeneric<T>(XmlNode token, out T outValue) where T : struct
{
2020-08-14 17:35:27 +00:00
if (token == null)
{
var name = nameof(token);
throw new ArgumentNullException(name);
}
try
{
string value = token.InnerText;
Type type = typeof(T);
object result = null;
if (type == typeof(int))
result = Formatting.ParseInt(value);
else if (type == typeof(float))
result = Formatting.ParseFloat(value);
else if (type == typeof(double))
result = Formatting.ParseDouble(value);
if (result == null)
{
Type resultType = typeof(T);
var converter = TypeDescriptor.GetConverter(resultType);
result = converter.ConvertFromString(token.InnerText);
}
outValue = (T)result;
return true;
}
2020-08-14 17:35:27 +00:00
catch (NotSupportedException)
{
2020-08-14 17:35:27 +00:00
outValue = default;
return false;
}
}
public static bool ReadPropertyGeneric<T>(Property prop, PropertyType propType, XmlNode token) where T : struct
{
2020-08-14 17:35:27 +00:00
if (prop == null)
{
var name = nameof(prop);
throw new ArgumentNullException(name);
}
2020-08-14 17:35:27 +00:00
if (ReadPropertyGeneric(token, out T result))
{
prop.Type = propType;
prop.Value = result;
return true;
}
return false;
}
public static IXmlPropertyToken GetHandler(string tokenName)
{
IXmlPropertyToken result = null;
if (Handlers.ContainsKey(tokenName))
result = Handlers[tokenName];
return result;
}
public static T GetHandler<T>() where T : IXmlPropertyToken
{
IXmlPropertyToken result = Handlers.Values
.Where(token => token is T)
.First();
return (T)result;
}
}
}