private BlobData ConvertBlob <T0, T1>(T0 obj, ScriptToBlobFunc <T0, T1> func, int identifier)
            where T0 : ScriptableObject
            where T1 : struct
        {
#if DETAIL_MARKERS
            using (m_createBlobWithFunc.Auto())
#endif
            {
                BlobAssetReference <T1> assetReference = func.Invoke(obj, this);

                return(BlobData.Create(assetReference, identifier));
            }
        }
        /// <summary>
        /// Converts a <see cref="ScriptableObject"/> of <see cref="T0"/> to a blob reference of <see cref="T1"/>.
        /// The user must provide a manual conversion function.
        /// The SO need not implement <see cref="IConvertScriptableObjectToBlob{T1}"/>, making it useful
        /// for converting pre-existing SO that are out of your control.
        /// </summary>
        /// <param name="obj">The SO to convert.</param>
        /// <param name="func">A delegate of <see cref="ScriptToBlobFunc{T0,T1}"/>. The concrete types must match.</param>
        /// <typeparam name="T0">The concrete type of the SO.</typeparam>
        /// <typeparam name="T1">Type of the struct our Blob asset will reference.</typeparam>
        /// <returns>The constructed <see cref="BlobAssetReference{T1}"/></returns>
        public BlobAssetReference <T1> GetBlob <T0, T1>(T0 obj, ScriptToBlobFunc <T0, T1> func)
            where T0 : ScriptableObject
            where T1 : struct
        {
            int identifier = new Vector2Int(obj.GetInstanceID(), func.GetHashCode()).GetHashCode();

            if (PreCheck(obj, identifier, out BlobAssetReference <T1> blob))
            {
                return(blob);
            }

            BlobData data = ConvertBlob(obj, func, identifier);

            return(PostCheck <T1>(identifier, data));
        }