// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using MessagePack.Formatters;
namespace MessagePack.Resolvers
{
///
/// Singleton version of CompositeResolver, which be able to register a collection of formatters and resolvers to a single instance.
///
public class StaticCompositeResolver : IFormatterResolver
{
public static readonly StaticCompositeResolver Instance = new StaticCompositeResolver();
private bool freezed;
private IReadOnlyList formatters;
private IReadOnlyList resolvers;
private StaticCompositeResolver()
{
formatters = Array.Empty();
resolvers = Array.Empty();
}
///
/// Initializes a singleton instance with the specified formatters.
/// This method can only call before use StaticCompositeResolver.Instance.GetFormatter.
/// If call twice in the Register methods, registered formatters and resolvers will be overridden.
///
///
/// A list of instances of .
/// The formatters are searched in the order given, so if two formatters support serializing the same type, the first one is used.
///
public void Register(params IMessagePackFormatter[] formatters)
{
if (this.freezed)
{
throw new InvalidOperationException("Register must call on startup(before use GetFormatter).");
}
if (this.formatters is null)
{
throw new ArgumentNullException(nameof(formatters));
}
this.formatters = formatters;
this.resolvers = Array.Empty();
}
///
/// Initializes a singleton instance with the specified formatters and sub-resolvers.
/// This method can only call before use StaticCompositeResolver.Instance.GetFormatter.
/// If call twice in the Register methods, registered formatters and resolvers will be overridden.
///
///
/// A list of resolvers to use for serializing types.
/// The resolvers are searched in the order given, so if two resolvers support serializing the same type, the first one is used.
///
public void Register(params IFormatterResolver[] resolvers)
{
if (this.freezed)
{
throw new InvalidOperationException("Register must call on startup(before use GetFormatter).");
}
if (resolvers is null)
{
throw new ArgumentNullException(nameof(resolvers));
}
this.formatters = Array.Empty();
this.resolvers = resolvers;
}
///
/// Initializes a singleton instance with the specified formatters and sub-resolvers.
/// This method can only call before use StaticCompositeResolver.Instance.GetFormatter.
/// If call twice in the Register methods, registered formatters and resolvers will be overridden.
///
///
/// A list of instances of .
/// The formatters are searched in the order given, so if two formatters support serializing the same type, the first one is used.
///
///
/// A list of resolvers to use for serializing types for which does not include a formatter.
/// The resolvers are searched in the order given, so if two resolvers support serializing the same type, the first one is used.
///
public void Register(IReadOnlyList formatters, IReadOnlyList resolvers)
{
if (this.freezed)
{
throw new InvalidOperationException("Register must call on startup(before use GetFormatter).");
}
if (formatters is null)
{
throw new ArgumentNullException(nameof(formatters));
}
if (resolvers is null)
{
throw new ArgumentNullException(nameof(resolvers));
}
this.formatters = formatters;
this.resolvers = resolvers;
}
///
/// Gets an instance that can serialize or deserialize some type .
///
/// The type of value to be serialized or deserialized.
/// A formatter, if this resolver supplies one for type ; otherwise null.
public IMessagePackFormatter GetFormatter()
{
return Cache.Formatter;
}
private static class Cache
{
public static readonly IMessagePackFormatter Formatter;
static Cache()
{
Instance.freezed = true;
foreach (var item in Instance.formatters)
{
if (item is IMessagePackFormatter f)
{
Formatter = f;
return;
}
}
foreach (var item in Instance.resolvers)
{
var f = item.GetFormatter();
if (f != null)
{
Formatter = f;
return;
}
}
}
}
}
}