// 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; } } } } } }