public DatastoreClientImpl(Datastore.IDatastoreClient grpcClient, DatastoreSettings settings)
        {
            this.GrpcClient = grpcClient;
            DatastoreSettings effectiveSettings = settings ?? DatastoreSettings.GetDefault();

            _clientHelper = new ClientHelper(effectiveSettings);
        }
        /// <summary>
        /// Synchronously creates a <see cref="DatastoreClient"/>, applying defaults for all unspecified settings.
        /// </summary>
        /// <param name="endpoint">Optional <see cref="ServiceEndpoint"/>.</param>
        /// <param name="settings">Optional <see cref="DatastoreSettings"/>.</param>
        /// <param name="credentials">Optional <see cref="ChannelCredentials"/>.</param>
        /// <returns>The created <see cref="DatastoreClient"/>.</returns>
        public static DatastoreClient Create(
            ServiceEndpoint endpoint       = null,
            DatastoreSettings settings     = null,
            ChannelCredentials credentials = null)
        {
            Channel channel = ClientHelper.CreateChannel(endpoint ?? DefaultEndpoint, credentials);

            Datastore.DatastoreClient grpcClient = new Datastore.DatastoreClient(channel);
            return(new DatastoreClientImpl(grpcClient, settings));
        }
        // Note: we could have parameterless overloads of Create and CreateAsync,
        // documented to just use the default endpoint, settings and credentials.
        // Pros:
        // - Might be more reassuring on first use
        // - Allows method group conversions
        // Con: overloads!

        /// <summary>
        /// Asynchronously creates a <see cref="DatastoreClient"/>, applying defaults for all unspecified settings.
        /// </summary>
        /// <param name="endpoint">Optional <see cref="ServiceEndpoint"/>.</param>
        /// <param name="settings">Optional <see cref="DatastoreSettings"/>.</param>
        /// <param name="credentials">Optional <see cref="ChannelCredentials"/>.</param>
        /// <returns>The task representing the created <see cref="DatastoreClient"/>.</returns>
        public static async Task <DatastoreClient> CreateAsync(
            ServiceEndpoint endpoint       = null,
            DatastoreSettings settings     = null,
            ChannelCredentials credentials = null)
        {
            Channel channel = await ClientHelper.CreateChannelAsync(endpoint ?? DefaultEndpoint, credentials).ConfigureAwait(false);

            Datastore.DatastoreClient grpcClient = new Datastore.DatastoreClient(channel);
            return(new DatastoreClientImpl(grpcClient, settings));
        }
 /// <summary>
 /// Wrap a GRPC Datastore client for more convenient use.
 /// </summary>
 /// <param name="grpcClient">A GRPC client to wrap.</param>
 /// <param name="settings">
 /// An optional <see cref="DatastoreSettings"/> to configure this wrapper.
 /// If null or not specified, then the default settings are used.
 /// </param>
 /// <returns>A <see cref="DatastoreClient"/> that wraps the specified GRPC client.</returns>
 public static DatastoreClient ToClient(
     this Datastore.IDatastoreClient grpcClient,
     DatastoreSettings settings = null
     ) => new DatastoreClientImpl(grpcClient, settings);