// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Concurrent;
using System.Reflection;
namespace EpicGames.Core
{
///
/// Base interface for a binary converter. Implementations must derive from instead
///
public interface IBinaryConverter
{
///
/// Converter version number
///
int Version { get; }
}
///
/// Interface for converting serializing object to and from a binary format
///
/// The value to serialize
public interface IBinaryConverter : IBinaryConverter
{
///
/// Reads a value from the archive
///
/// The archive reader
/// New instance of the value
TValue Read(BinaryArchiveReader reader);
///
/// Writes a value to the archive
///
/// The archive writer
/// The value to write
void Write(BinaryArchiveWriter writer, TValue value);
}
///
/// Registration of IBinaryConverter instances
///
public static class BinaryConverter
{
///
/// Map from type to the converter type
///
static readonly ConcurrentDictionary s_typeToConverterType = new ConcurrentDictionary();
///
/// Explicitly register the converter for a type. If Type is a generic type, the converter should also be a generic type with the same type arguments.
///
/// Type to register a converter for
/// The converter type
public static void RegisterConverter(Type type, Type converterType)
{
if (!s_typeToConverterType.TryAdd(type, converterType))
{
throw new Exception($"Type '{type.Name}' already has a registered converter ({s_typeToConverterType[type].Name})");
}
}
///
/// Attempts to get the converter for a particular type
///
/// The type to use
/// The converter type
/// True if a converter was found
public static bool TryGetConverterType(Type type, out Type? converterType)
{
if (s_typeToConverterType.TryGetValue(type, out Type? customConverterType))
{
converterType = customConverterType;
return true;
}
BinaryConverterAttribute? converterAttribute = type.GetCustomAttribute();
if (converterAttribute != null)
{
converterType = converterAttribute.Type;
return true;
}
if (type.IsGenericType)
{
BinaryConverterAttribute? genericConverterAttribute = type.GetGenericTypeDefinition().GetCustomAttribute();
if (genericConverterAttribute != null)
{
converterType = genericConverterAttribute.Type.MakeGenericType(type.GetGenericArguments());
return true;
}
}
converterType = null;
return false;
}
}
}