| File: Files\HostedFileClientBuilder.cs | |
| Project: ..\..\..\src\Libraries\Microsoft.Extensions.AI\Microsoft.Extensions.AI.csproj (Microsoft.Extensions.AI) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Microsoft.Shared.DiagnosticIds; using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.AI; /// <summary>A builder for creating pipelines of <see cref="IHostedFileClient"/>.</summary> [Experimental(DiagnosticIds.Experiments.AIFiles, UrlFormat = DiagnosticIds.UrlFormat)] public sealed class HostedFileClientBuilder { private readonly Func<IServiceProvider, IHostedFileClient> _innerClientFactory; /// <summary>The registered client factory instances.</summary> private List<Func<IHostedFileClient, IServiceProvider, IHostedFileClient>>? _clientFactories; /// <summary>Initializes a new instance of the <see cref="HostedFileClientBuilder"/> class.</summary> /// <param name="innerClient">The inner <see cref="IHostedFileClient"/> that represents the underlying backend.</param> /// <exception cref="ArgumentNullException"><paramref name="innerClient"/> is <see langword="null"/>.</exception> public HostedFileClientBuilder(IHostedFileClient innerClient) { _ = Throw.IfNull(innerClient); _innerClientFactory = _ => innerClient; } /// <summary>Initializes a new instance of the <see cref="HostedFileClientBuilder"/> class.</summary> /// <param name="innerClientFactory">A callback that produces the inner <see cref="IHostedFileClient"/> that represents the underlying backend.</param> /// <exception cref="ArgumentNullException"><paramref name="innerClientFactory"/> is <see langword="null"/>.</exception> public HostedFileClientBuilder(Func<IServiceProvider, IHostedFileClient> innerClientFactory) { _innerClientFactory = Throw.IfNull(innerClientFactory); } /// <summary>Builds an <see cref="IHostedFileClient"/> that represents the entire pipeline. Calls to this instance will pass through each of the pipeline stages in turn.</summary> /// <param name="services"> /// The <see cref="IServiceProvider"/> that should provide services to the <see cref="IHostedFileClient"/> instances. /// If <see langword="null"/>, an empty <see cref="IServiceProvider"/> will be used. /// </param> /// <returns>An instance of <see cref="IHostedFileClient"/> that represents the entire pipeline.</returns> /// <exception cref="InvalidOperationException">A factory returned <see langword="null"/>.</exception> public IHostedFileClient Build(IServiceProvider? services = null) { services ??= EmptyServiceProvider.Instance; var fileClient = _innerClientFactory(services); // To match intuitive expectations, apply the factories in reverse order, so that the first factory added is the outermost. if (_clientFactories is not null) { for (var i = _clientFactories.Count - 1; i >= 0; i--) { fileClient = _clientFactories[i](fileClient, services); if (fileClient is null) { Throw.InvalidOperationException( $"The {nameof(HostedFileClientBuilder)} entry at index {i} returned null. " + $"Ensure that the callbacks passed to {nameof(Use)} return non-null {nameof(IHostedFileClient)} instances."); } } } return fileClient; } /// <summary>Adds a factory for an intermediate hosted file client to the hosted file client pipeline.</summary> /// <param name="clientFactory">The client factory function.</param> /// <returns>The updated <see cref="HostedFileClientBuilder"/> instance.</returns> /// <exception cref="ArgumentNullException"><paramref name="clientFactory"/> is <see langword="null"/>.</exception> public HostedFileClientBuilder Use(Func<IHostedFileClient, IHostedFileClient> clientFactory) { _ = Throw.IfNull(clientFactory); return Use((innerClient, _) => clientFactory(innerClient)); } /// <summary>Adds a factory for an intermediate hosted file client to the hosted file client pipeline.</summary> /// <param name="clientFactory">The client factory function.</param> /// <returns>The updated <see cref="HostedFileClientBuilder"/> instance.</returns> /// <exception cref="ArgumentNullException"><paramref name="clientFactory"/> is <see langword="null"/>.</exception> public HostedFileClientBuilder Use(Func<IHostedFileClient, IServiceProvider, IHostedFileClient> clientFactory) { _ = Throw.IfNull(clientFactory); (_clientFactories ??= []).Add(clientFactory); return this; } }