You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

整洁架构下如何在应用层实现DTF框架的抽象?

结论先行

  1. DTF 确实属于基础设施层:它是第三方工作流调度实现,不属于业务逻辑范畴,符合整洁架构中基础设施层存放外部工具、第三方依赖实现的定位。
  2. 完全可以实现应用层完全不感知DTF的存在,核心思路是通过依赖倒置原则+适配器模式,将DTF的所有实现细节隔离在基础设施层,具体实现方案如下:

实现步骤

第一步:应用层定义业务无关的编排抽象

应用层只定义工作流的核心能力接口,不引入任何DTF相关的依赖:

// 应用层的编排抽象
public interface IOrchestration<TInput, TOutput>
{
    Task<TOutput> RunAsync(IOrchestrationContext context, TInput input);
}

// 应用层的活动抽象
public interface IActivity<TInput, TOutput>
{
    Task<TOutput> ExecuteAsync(TInput input);
}

// 应用层的编排上下文抽象,只暴露业务需要的方法
public interface IOrchestrationContext
{
    Task<TOutput> ScheduleActivityAsync<TActivity, TInput, TOutput>(TInput input)
        where TActivity : IActivity<TInput, TOutput>;
}

// 应用层的编排触发客户端抽象
public interface IWorkflowClient
{
    Task StartAsync<TOrchestration, TInput>(TInput input)
        where TOrchestration : IOrchestration<TInput, object>;
}

第二步:应用层实现纯业务的工作流逻辑

所有的业务流程定义完全基于上面的抽象,和DTF没有任何耦合:

// 应用层的视频编码活动(业务逻辑在这里)
public class EncodeVideoActivity : IActivity<string, string>
{
    // 可自由注入应用层的其他服务,比如存储服务、媒体处理服务等
    public async Task<string> ExecuteAsync(string input)
    {
        // 业务逻辑:编码视频
        return "http://<azurebloblocation>/encoded_video.avi";
    }
}

// 应用层的发送邮件活动
public class SendEmailActivity : IActivity<string, object>
{
    public async Task<object> ExecuteAsync(string input)
    {
        // 业务逻辑:给用户发通知邮件
        return null;
    }
}

// 应用层的视频编码编排(业务流程定义在这里)
public class EncodeVideoOrchestration : IOrchestration<string, string>
{
    public async Task<string> RunAsync(IOrchestrationContext context, string input)
    {
        string encodedUrl = await context.ScheduleActivityAsync<EncodeVideoActivity, string, string>(input);
        await context.ScheduleActivityAsync<SendEmailActivity, string, object>(input);
        return encodedUrl;
    }
}

第三步:基础设施层实现DTF适配

所有和DTF相关的实现都放在基础设施层,通过适配器把DTF的原生能力和应用层的抽象做对接:

// 基础设施层:Orchestration适配器,对接DTF原生Orchestration和应用层IOrchestration
public class DTFOrchestrationAdapter<TOrchestration, TInput, TOutput> : TaskOrchestration<TOutput, TInput>
    where TOrchestration : IOrchestration<TInput, TOutput>
{
    private readonly TOrchestration _orchestration;

    public DTFOrchestrationAdapter(TOrchestration orchestration)
    {
        _orchestration = orchestration;
    }

    public override async Task<TOutput> RunTask(OrchestrationContext context, TInput input)
    {
        // 把DTF的原生上下文封装成应用层定义的IOrchestrationContext
        var appContext = new DTFOrchestrationContextAdapter(context);
        return await _orchestration.RunAsync(appContext, input);
    }
}

// 基础设施层:Activity适配器
public class DTFActivityAdapter<TActivity, TInput, TOutput> : TaskActivity<TInput, TOutput>
    where TActivity : IActivity<TInput, TOutput>
{
    private readonly TActivity _activity;

    public DTFActivityAdapter(TActivity activity)
    {
        _activity = activity;
    }

    protected override async Task<TOutput> ExecuteAsync(TaskContext context, TInput input)
    {
        return await _activity.ExecuteAsync(input);
    }
}

// 基础设施层:上下文适配器
public class DTFOrchestrationContextAdapter : IOrchestrationContext
{
    private readonly OrchestrationContext _dtfContext;

    public DTFOrchestrationContextAdapter(OrchestrationContext dtfContext)
    {
        _dtfContext = dtfContext;
    }

    public async Task<TOutput> ScheduleActivityAsync<TActivity, TInput, TOutput>(TInput input)
        where TActivity : IActivity<TInput, TOutput>
    {
        // 内部调用DTF原生调度方法,适配成应用层定义的接口调用
        return await _dtfContext.ScheduleTask<TOutput>(typeof(DTFActivityAdapter<TActivity, TInput, TOutput>), input);
    }
}

// 基础设施层:WorkflowClient实现
public class DTFWorkflowClient : IWorkflowClient
{
    private readonly TaskHubClient _dtfClient;

    public DTFWorkflowClient(TaskHubClient dtfClient)
    {
        _dtfClient = dtfClient;
    }

    public async Task StartAsync<TOrchestration, TInput>(TInput input)
        where TOrchestration : IOrchestration<TInput, object>
    {
        await _dtfClient.CreateOrchestrationInstance(typeof(DTFOrchestrationAdapter<TOrchestration, TInput, object>), input);
    }
}

第四步:服务注册和启动逻辑放到入口层

所有DTF的初始化、适配器的注册都放在Program.cs等入口层,应用层完全不需要感知:

// 入口层Program.cs
var builder = Host.CreateDefaultBuilder(args);

// 注册应用层的编排和活动
builder.Services.AddScoped<EncodeVideoOrchestration>();
builder.Services.AddScoped<EncodeVideoActivity>();
builder.Services.AddScoped<SendEmailActivity>();

// 注册DTF相关服务
builder.Services.AddSingleton<TaskHubClient>(sp => new TaskHubClient("myvideohub", "connectionDetails"));
builder.Services.AddSingleton<IWorkflowClient, DTFWorkflowClient>();

// 启动DTF Worker
var hubWorker = new TaskHubWorker("myvideohub", "connectionDetails")
    // 注册适配后的编排和活动
    .AddTaskOrchestrations(typeof(DTFOrchestrationAdapter<EncodeVideoOrchestration, string, string>))
    .AddTaskActivities(typeof(DTFActivityAdapter<EncodeVideoActivity, string, string>), typeof(DTFActivityAdapter<SendEmailActivity, string, object>))
    .Start();

var app = builder.Build();
app.Run();

最终效果

  • 应用层所有代码完全不依赖DTF的任何类型,只依赖自己定义的抽象
  • 后续如果需要替换工作流实现,只需要在基础设施层新增对应框架的适配代码即可,应用层的业务逻辑、流程定义不需要做任何修改
  • 完全符合整洁架构的依赖规则:内层不依赖外层,外层实现内层定义的抽象

内容的提问来源于stack exchange,提问作者DarkLeafyGreen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 09:15:04