Skip to content

自定义资源 ​

更新: 2026-10-16 15:20:09   字数: 0 字   时长: 0 分钟

Aspire 内置了项目、容器、可执行文件等资源类型,集成包又补充了大量常见服务。当这些都覆盖不到时,您可以定义自定义资源。

什么时候需要自定义资源 ​

场景说明
内部平台或自研中间件官方与社区都不会有对应集成。
需要把「非进程型资源」纳入应用模型例如一个 SaaS 服务、一个外部 API 端点。
需要自定义仪表板展示与操作自定义资源类型 + 自定义命令 + 自定义 URL。
需要参与发布流水线让资源在部署时生成特定产物。

最小自定义资源 ​

1. 定义资源类型 ​

csharp
using Aspire.Hosting.ApplicationModel;

public sealed class ThirdPartyApiResource(string name) : Resource(name)
{
    public required string BaseUrl { get; init; }
}

大多数内置资源都继承 Resource 基类;如果资源需要提供连接信息,可以实现 IResourceWithConnectionString。

2. 提供扩展方法 ​

csharp
public static class ThirdPartyApiResourceBuilderExtensions
{
    public static IResourceBuilder<ThirdPartyApiResource> AddThirdPartyApi(
        this IDistributedApplicationBuilder builder,
        [ResourceName] string name,
        string baseUrl)
    {
        var resource = new ThirdPartyApiResource(name) { BaseUrl = baseUrl };

        return builder.AddResource(resource)
            .WithInitialState(new CustomResourceSnapshot
            {
                ResourceType = "ThirdPartyApi",
                State = "Running",
                Properties = [new("BaseUrl", baseUrl)]
            });
    }
}

在 AppHost 中使用:

csharp
var api = builder.AddThirdPartyApi("partner", "https://api.partner.example.com");

builder.AddProject<Projects.Web>("web")
    .WithReference(api);

[ResourceName] 特性

给 name 参数加上 [ResourceName] 可以让 IDE 在调用处提供校验与提示,官方的 Add* 方法都这样做。

让资源支持引用 ​

如果资源能提供连接信息,实现 IResourceWithConnectionString:

csharp
public sealed class ThirdPartyApiResource(string name)
    : Resource(name), IResourceWithConnectionString
{
    public required string BaseUrl { get; init; }
    public required IResourceBuilder<ParameterResource> ApiKey { get; init; }

    public ReferenceExpression ConnectionStringExpression =>
        ReferenceExpression.Create($"{BaseUrl};ApiKey={ApiKey.Resource.ValueExpression}");
}

用 ReferenceExpression 而不是字符串拼接

参数值可能在部署时才能确定,直接拼接字符串会在构建期就把值固化下来。

仪表板呈现 ​

初始状态与属性 ​

csharp
builder.AddResource(resource)
    .WithInitialState(new CustomResourceSnapshot
    {
        ResourceType = "ThirdPartyApi",
        State = "Running",
        Properties =
        [
            new("Region", "cn-east-2"),
            new("Tier", "Standard")
        ],
        Urls = [new("https://api.partner.example.com", "合作伙伴控制台")]
    });

健康检查 ​

csharp
builder.AddResource(resource)
    .WithHealthCheck("partner-api-ready");

自定义命令 ​

让用户可以在仪表板上对资源执行操作:

csharp
builder.AddResource(resource)
    .WithCommand("rotate-key", "轮换密钥", async context =>
    {
        // 执行轮换逻辑
        return CommandResults.Success();
    });

自定义 URL ​

csharp
builder.AddResource(resource)
    .WithUrl("https://portal.partner.example.com", "合作伙伴门户");

参与发布与部署 ​

概念用途
PublishAsConnectionString()发布时只输出连接字符串,不做资源映射。
publishing / deploying 步骤在流水线中插入自定义逻辑。
注解(IResourceAnnotation)向发布器传递资源元数据。

测试自定义资源 ​

自定义资源与注解同样可以被测试覆盖:

csharp
[Fact]
public async Task Custom_Resource_Should_Expose_Expected_Url()
{
    var appHost = await DistributedApplicationTestingBuilder
        .CreateAsync<Projects.MyApp_AppHost>();

    await using var app = await appHost.BuildAsync();

    var resource = app.Resources.GetResource("partner");

    Assert.NotEmpty(resource.Annotations.OfType<ResourceUrlAnnotation>());
}

最佳实践 ​

  • 一个注解只做一件事:不要写一个「万能配置注解」。(反面例子:ConfigAnnotation 同时塞进重试策略、日志设置与安全设置。)
  • 名称要有意义:DatabaseConnectionPoolAnnotation 比 DbAnnotation 好。
  • 遵循构建器模式:扩展方法返回 IResourceBuilder<T> 以支持链式调用。
  • 提供 XML 文档:注解与扩展方法都应写注释。
  • 提供合理默认值,让最简单的调用就能工作。
  • 本地实现优先:能提供容器或模拟器实现的自定义资源,价值远高于只能连真实服务的资源。

相关阅读 ​

你觉得这篇文章怎么样?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
评论
  • 按正序
  • 按倒序
  • 按热度