protected static void Attach
            (AnnotationsContext context, IGraphClient graphClient,
            EntityResolver resolver, EntityConverter converter)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (graphClient == null)
            {
                throw new ArgumentNullException(nameof(graphClient));
            }

            if (resolver == null && converter == null)
            {
                throw new InvalidOperationException(Messages.NoResolverOrConverterError);
            }
            if (resolver != null && converter != null)
            {
                throw new InvalidOperationException(Messages.BothResolverAndConverterError);
            }

            //if (entityTypes == null || entityTypes.FirstOrDefault() == null)
            //{
            //    throw new ArgumentNullException(nameof(entityTypes), "Neo4jClient.DataAnnotations needs to know all your entity types (including complex types) and their derived types aforehand in order to do efficient work.");
            //}

            var _converters = graphClient.JsonConverters;

            if (_converters == null)
            {
                _converters = new List <JsonConverter>();
            }

            if (resolver != null)
            {
                resolver.AnnotationsContext = context;
                //EntityResolver = entityResolver;

                var dummyConverterType = typeof(EntityResolverConverter);
                if (_converters.FirstOrDefault(c => dummyConverterType.IsAssignableFrom(c.GetType())) is
                    EntityResolverConverter existingConverter)
                {
                    _converters.Remove(existingConverter);
                }

                graphClient.JsonContractResolver = resolver;

                //add a dummy converter that just proxies entityresolver deserialization
                //we do this because neo4jclient currently doesn't use ContractResolvers at deserialization, but they use converters.
                _converters.Add(resolver.DeserializeConverter);
            }

            if (converter != null)
            {
                converter.AnnotationsContext = context;
                //EntityConverter = entityConverter;

                var entityConverterType = typeof(EntityConverter);
                if (_converters.FirstOrDefault(c => entityConverterType.IsAssignableFrom(c.GetType())) is
                    EntityConverter existingConverter)
                {
                    _converters.Remove(existingConverter);
                }

                //we may have to mix this two (resolver and converter) eventually because of some choices of the neo4jclient team.
                //entityConverter._canRead = true;
                _converters.Add(converter);
            }

            if (_converters.Count > 0 && graphClient.JsonConverters != _converters) //!= existingConverters?.Length)
            {
                try
                {
                    //try reflection to set the converters in the original array
                    Utils.Utilities.GetBackingField(graphClient.GetType()
                                                    .GetProperty("JsonConverters",
                                                                 BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
                    .SetValue(graphClient, _converters);
                }
                catch
                {
                }
            }

            if (graphClient is IBoltGraphClient)
            {
                if (!graphClient.IsConnected)
                {
                    //connection is required at this point for bolt clients
                    throw new InvalidOperationException(Messages.ClientIsNotConnectedError);
                }

                dynamic driverMemberInfo = null;

                var driverProperty = graphClient
                                     .GetType()
                                     .GetProperty("Driver", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

                if (driverProperty != null && !driverProperty.CanWrite)
                {
                    FieldInfo driverBackingField = null;

                    try
                    {
                        //try reflection to set the driver via backing field
                        driverBackingField = Utils.Utilities.GetBackingField(driverProperty);
                        driverMemberInfo   = driverBackingField;
                    }
                    catch
                    {
                    }
                }
                else
                {
                    driverMemberInfo = driverProperty;
                }

                var driver = driverMemberInfo?.GetValue(graphClient) as IDriver;
                if (driver == null)
                {
                    //this isn't supposed to happen
                    throw new InvalidOperationException(Messages.ClientHasNoDriverError);
                }

                //now wrap the driver with our wrappers
                driver = new DriverWrapper(driver);

                try
                {
                    //replace the driver
                    driverMemberInfo?.SetValue(graphClient, driver);
                }
                catch
                {
                }
            }
        }