public SerializerPair GetOrRegisterSerializerPair()

in rd-net/RdFramework.Reflection/ReflectionSerializers.cs [80:163]


  public SerializerPair GetOrRegisterSerializerPair(Type type, bool instance = false)
  {
    lock (myLock)
    {
      var implementingType = ReflectionSerializerVerifier.GetImplementingType(type.GetTypeInfo()).GetTypeInfo();
      var isRdType = implementingType != type;

      if (!isRdType && instance && SerializerReflectionUtil.CanBePolymorphic(type))
      {
        myCatalog.AddType(type);
        if (myInstanceSerializers.TryGetValue(type, out var pair))
          return pair;

        BeforeCreation.Fire(type);

        if (myInstanceSerializers.TryGetValue(type, out pair))
          return pair;

        return GetPolymorphic(type);
      }

      if (!myStaticSerializers.TryGetValue(type, out var serializerPair))
      {
        using var info = new FirstChanceExceptionInterceptor.ThreadLocalDebugInfo(type);

        myCatalog.AddType(type);
        
        BeforeCreation.Fire(type);

        if (myStaticSerializers.TryGetValue(type, out serializerPair))
          return serializerPair;

        if (Mode.IsAssertion) myCurrentSerializersChain.Enqueue(type);
        try
        {
          myStaticSerializers.Add(type, null!);

          if (isRdType)
          {
            var builtIn = BuiltInSerializers.TryGet(implementingType, t => GetOrRegisterSerializerPair(t, true));
            Assertion.AssertNotNull(builtIn, "Unable to get built in serializer for type {0}, thought it should be implemented for Rd-types.", type);
            var pair = SerializerReflectionUtil.ConvertPair(builtIn, type);

            myStaticSerializers[type] = pair;
          }
          else if (ReflectionSerializerVerifier.IsScalar(type))
          {
            myStaticSerializers[type] = CreateScalar(type, instance);
          }
          else if (BuiltInSerializers.Has(type.GetTypeInfo()))
          {
            var builtIn = BuiltInSerializers.TryGet(
              type.GetTypeInfo(),
              t => GetOrRegisterSerializerPair(t, true));
            Assertion.AssertNotNull(builtIn, "Unable to get built in serializer for type {0}, thought API detect the presense of it. Probably it was only partially implemented",
              type);
            myStaticSerializers[type] = builtIn;
          }
          else
          {
            ReflectionUtil.InvokeGenericThis(this, nameof(RegisterModelSerializer), type);
          }
        }
        finally
        {
          if (Mode.IsAssertion) myCurrentSerializersChain.Dequeue();
        }

        if (!myStaticSerializers.TryGetValue(type, out serializerPair))
        {
          throw new KeyNotFoundException($"Unable to register type {type.ToString(true)}: serializer can't be found");
        }
      }

      if (Mode.IsAssertion && serializerPair == null)
        Assertion.Fail(
          $"Unable to create serializer for {type.ToString(true)}: circular dependency detected: {Join(" -> ", myCurrentSerializersChain.Select(t => t.ToString(true)).ToArray())}");
      else
        Assertion.AssertNotNull(serializerPair,
          $"Unable to register type: {type.ToString(true)}, undetected circular dependency. Enable Mode.IsAssertion to get the cycle.");

      return serializerPair;
    }
  }