File: Ats\BuilderExports.cs
Web Access
Project: src\src\Aspire.Hosting\Aspire.Hosting.csproj (Aspire.Hosting)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Aspire.Hosting.ApplicationModel;
using Aspire.Hosting.Eventing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
 
namespace Aspire.Hosting.Ats;
 
/// <summary>
/// ATS exports for <see cref="IDistributedApplicationBuilder"/> properties and related types.
/// </summary>
/// <remarks>
/// <para>
/// The <see cref="IDistributedApplicationBuilder"/> is the central type for defining Aspire applications.
/// This class exposes its properties (Configuration, Environment, AppHostDirectory) and provides
/// capabilities to interact with each of them.
/// </para>
/// <para>
/// <strong>Builder Properties:</strong>
/// <list type="bullet">
///   <item><description><c>Configuration</c> - Application configuration (connection strings, settings)</description></item>
///   <item><description><c>Environment</c> - Host environment info (name, isDevelopment)</description></item>
///   <item><description><c>AppHostDirectory</c> - Directory containing the app host</description></item>
/// </list>
/// </para>
/// <para>
/// <strong>Lifecycle Events:</strong>
/// <list type="bullet">
///   <item><description><c>subscribeBeforeStart</c> - Called before the application starts</description></item>
///   <item><description><c>subscribeAfterResourcesCreated</c> - Called after resources are created</description></item>
/// </list>
/// </para>
/// </remarks>
internal static class BuilderExports
{
    // Note: Configuration, Environment, AppHostDirectory, and ExecutionContext are accessed via property getters
    // on IDistributedApplicationBuilder which has [AspireExport(ExposeProperties = true)].
 
    #region Configuration
 
    /// <summary>
    /// Gets a configuration value by key.
    /// </summary>
    /// <param name="configuration">The configuration handle.</param>
    /// <param name="key">The configuration key (e.g., "ConnectionStrings:Default").</param>
    /// <returns>The configuration value, or null if not found.</returns>
    [AspireExport("getConfigValue", Description = "Gets a configuration value by key")]
    public static string? GetConfigValue(IConfiguration configuration, string key)
    {
        return configuration[key];
    }
 
    /// <summary>
    /// Gets a connection string by name.
    /// </summary>
    /// <param name="configuration">The configuration handle.</param>
    /// <param name="name">The connection string name.</param>
    /// <returns>The connection string value, or null if not found.</returns>
    [AspireExport("getConnectionString", Description = "Gets a connection string by name")]
    public static string? GetConnectionString(IConfiguration configuration, string name)
    {
        return configuration.GetConnectionString(name);
    }
 
    #endregion
 
    #region Host Environment
 
    /// <summary>
    /// Gets the environment name (e.g., "Development", "Production").
    /// </summary>
    /// <param name="environment">The host environment handle.</param>
    /// <returns>The environment name.</returns>
    [AspireExport("getEnvironmentName", Description = "Gets the environment name")]
    public static string GetEnvironmentName(IHostEnvironment environment)
    {
        return environment.EnvironmentName;
    }
 
    /// <summary>
    /// Checks if the environment is Development.
    /// </summary>
    /// <param name="environment">The host environment handle.</param>
    /// <returns>True if running in Development environment.</returns>
    [AspireExport("isDevelopment", Description = "Checks if running in Development environment")]
    public static bool IsDevelopment(IHostEnvironment environment)
    {
        return environment.IsDevelopment();
    }
 
    #endregion
 
    #region Lifecycle Events
 
    /// <summary>
    /// Subscribes to the BeforeStart event, which fires before the application starts.
    /// </summary>
    /// <remarks>
    /// This event provides access to the service provider and distributed application model,
    /// allowing you to perform final configuration or validation before resources start.
    /// </remarks>
    /// <param name="builder">The builder handle.</param>
    /// <param name="callback">A callback that receives the service provider when the event fires.</param>
    /// <returns>A subscription handle that can be used to unsubscribe.</returns>
    [AspireExport("subscribeBeforeStart", Description = "Subscribes to the BeforeStart lifecycle event")]
    public static DistributedApplicationEventSubscription SubscribeBeforeStart(
        IDistributedApplicationBuilder builder,
        Func<IServiceProvider, Task> callback)
    {
        return builder.Eventing.Subscribe<BeforeStartEvent>(async (@event, ct) =>
        {
            await callback(@event.Services).ConfigureAwait(false);
        });
    }
 
    /// <summary>
    /// Subscribes to the AfterResourcesCreated event, which fires after all resources are created.
    /// </summary>
    /// <remarks>
    /// At this point, all resources have been instantiated but may not yet be running.
    /// This is useful for performing cross-resource configuration.
    /// </remarks>
    /// <param name="builder">The builder handle.</param>
    /// <param name="callback">A callback that receives the service provider when the event fires.</param>
    /// <returns>A subscription handle that can be used to unsubscribe.</returns>
    [AspireExport("subscribeAfterResourcesCreated", Description = "Subscribes to the AfterResourcesCreated lifecycle event")]
    public static DistributedApplicationEventSubscription SubscribeAfterResourcesCreated(
        IDistributedApplicationBuilder builder,
        Func<IServiceProvider, Task> callback)
    {
        return builder.Eventing.Subscribe<AfterResourcesCreatedEvent>(async (@event, ct) =>
        {
            await callback(@event.Services).ConfigureAwait(false);
        });
    }
 
    #endregion
}