mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-07-08 18:06:41 +00:00
Static implementations using reflection go away
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Deserializers
|
||||
@@ -9,7 +7,10 @@ namespace SabreTools.Serialization.Deserializers
|
||||
/// Base class for all binary deserializers
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">Type of the model to deserialize</typeparam>
|
||||
/// <remarks>These methods assume there is a concrete implementation of the deserialzier for the model available</remarks>
|
||||
/// <remarks>
|
||||
/// This class allows all inheriting types to only implement <see cref="IStreamDeserializer<>"/>
|
||||
/// and still implicitly implement <see cref="IByteDeserializer<>"/> and <see cref="IFileDeserializer<>"/>
|
||||
/// </remarks>
|
||||
public abstract class BaseBinaryDeserializer<TModel> :
|
||||
IByteDeserializer<TModel>,
|
||||
IFileDeserializer<TModel>,
|
||||
@@ -57,110 +58,5 @@ namespace SabreTools.Serialization.Deserializers
|
||||
public abstract TModel? Deserialize(Stream? data);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Static Implementations
|
||||
|
||||
/// <inheritdoc cref="IByteDeserializer.Deserialize(byte[]?, int)"/>
|
||||
public static TModel? DeserializeBytes(byte[]? data, int offset)
|
||||
{
|
||||
var deserializer = GetType<IByteDeserializer<TModel>>();
|
||||
if (deserializer == null)
|
||||
return default;
|
||||
|
||||
return deserializer.Deserialize(data, offset);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileDeserializer.Deserialize(string?)"/>
|
||||
public static TModel? DeserializeFile(string? path)
|
||||
{
|
||||
var deserializer = GetType<IFileDeserializer<TModel>>();
|
||||
if (deserializer == null)
|
||||
return default;
|
||||
|
||||
return deserializer.Deserialize(path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStreamDeserializer.Deserialize(Stream?)"/>
|
||||
public static TModel? DeserializeStream(Stream? data)
|
||||
{
|
||||
var deserializer = GetType<IStreamDeserializer<TModel>>();
|
||||
if (deserializer == null)
|
||||
return default;
|
||||
|
||||
return deserializer.Deserialize(data);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Get a constructed instance of a type, if possible
|
||||
/// </summary>
|
||||
/// <typeparam name="TDeserializer">Deserializer type to construct</typeparam>
|
||||
/// <returns>Deserializer of the requested type, null on error</returns>
|
||||
private static TDeserializer? GetType<TDeserializer>()
|
||||
{
|
||||
// If the deserializer type is invalid
|
||||
string? deserializerName = typeof(TDeserializer)?.Name;
|
||||
if (deserializerName == null)
|
||||
return default;
|
||||
|
||||
// If the deserializer has no generic arguments
|
||||
var genericArgs = typeof(TDeserializer).GetGenericArguments();
|
||||
if (genericArgs.Length == 0)
|
||||
return default;
|
||||
|
||||
// Loop through all loaded assemblies
|
||||
Type modelType = genericArgs[0];
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
// If the assembly is invalid
|
||||
if (assembly == null)
|
||||
return default;
|
||||
|
||||
// If not all types can be loaded, use the ones that could be
|
||||
Type?[] assemblyTypes = [];
|
||||
try
|
||||
{
|
||||
assemblyTypes = assembly.GetTypes();
|
||||
}
|
||||
catch (ReflectionTypeLoadException rtle)
|
||||
{
|
||||
assemblyTypes = rtle.Types ?? [];
|
||||
}
|
||||
|
||||
// Loop through all types
|
||||
foreach (Type? type in assemblyTypes)
|
||||
{
|
||||
// If the type is invalid
|
||||
if (type == null)
|
||||
continue;
|
||||
|
||||
// If the type isn't a class
|
||||
if (!type.IsClass)
|
||||
continue;
|
||||
|
||||
// If the type doesn't implement the interface
|
||||
var interfaceType = type.GetInterface(deserializerName);
|
||||
if (interfaceType == null)
|
||||
continue;
|
||||
|
||||
// If the interface doesn't use the correct type parameter
|
||||
var genericTypes = interfaceType.GetGenericArguments();
|
||||
if (genericTypes.Length != 1 || genericTypes[0] != modelType)
|
||||
continue;
|
||||
|
||||
// Try to create a concrete instance of the type
|
||||
var instance = (TDeserializer?)Activator.CreateInstance(type);
|
||||
if (instance != null)
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user