Browse Source

fix: fix event serializer

pull/427/head
cKey 4 years ago
parent
commit
defeb6504d
  1. 1
      aspnet-core/.gitignore
  2. 51
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.LifeCycleEvent/LINGYUN/Abp/WorkflowCore/LifeCycleEvent/AbpEventBusLifeCycleEventHub.cs
  3. 86
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.LifeCycleEvent/LINGYUN/Abp/WorkflowCore/LifeCycleEvent/AbpEventBusProvider.cs
  4. 22
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.LifeCycleEvent/LINGYUN/Abp/WorkflowCore/LifeCycleEvent/AbpWorkflowCoreLifeCycleEventModule.cs
  5. 45
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.LifeCycleEvent/LINGYUN/Abp/WorkflowCore/LifeCycleEvent/LifeCycleEventHandler.cs
  6. 12
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.LifeCycleEvent/LINGYUN/Abp/WorkflowCore/LifeCycleEvent/LifeCycleEventWrap.cs
  7. 47
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinition.cs
  8. 30
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinitionConditionCondition.cs
  9. 37
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinitionConditionNode.cs
  10. 10
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinitionExtensions.cs
  11. 52
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinitionFormData.cs
  12. 47
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinitionNode.cs
  13. 28
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinitionStepBody.cs
  14. 15
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowCorePersistenceModule.cs
  15. 2
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/WorkflowDbProperties.cs
  16. 11
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpRabbitMQWorkflowCoreOptions.cs
  17. 47
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpRabbitMqQueueProvider.cs
  18. 8
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpWorkflowCoreRabbitMQModule.cs
  19. 17
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/QueueNameNormalizer.cs
  20. 4
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/WorkflowQueueConfiguration.cs
  21. 9
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpWorkflowCoreModule.cs
  22. 8
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowBase.cs
  23. 9
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowConditionCondition.cs
  24. 15
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowConditionNode.cs
  25. 18
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowDefine.cs
  26. 17
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowDefinition.cs
  27. 24
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowFormData.cs
  28. 105
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowManager.cs
  29. 20
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowNode.cs
  30. 10
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowParam.cs
  31. 8
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowParamDictionary.cs
  32. 8
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowParamInput.cs
  33. 20
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowStepBody.cs
  34. 8
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/System/ObjectSerializerExtensions.cs
  35. 1
      aspnet-core/tests/LINGYUN.Abp.WorkflowCore.Tests/LINGYUN.Abp.WorkflowCore.Tests.csproj

1
aspnet-core/.gitignore

@ -4,3 +4,4 @@ LocalNuget
**/*.csproj.user **/*.csproj.user
templates templates
nupkg nupkg
consoles

51
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.LifeCycleEvent/LINGYUN/Abp/WorkflowCore/LifeCycleEvent/AbpEventBusLifeCycleEventHub.cs

@ -1,51 +0,0 @@
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
using Volo.Abp.EventBus.Distributed;
using WorkflowCore.Interface;
using EventData = WorkflowCore.Models.LifeCycleEvents.LifeCycleEvent;
namespace LINGYUN.Abp.WorkflowCore.LifeCycleEvent
{
public class AbpEventBusLifeCycleEventHub : ILifeCycleEventHub
{
private IDisposable _subscriber;
private readonly IDistributedEventBus _eventBus;
private readonly ILoggerFactory _loggerFactory;
public AbpEventBusLifeCycleEventHub(
ILoggerFactory loggerFactory,
IDistributedEventBus distributedEventBus)
{
_loggerFactory = loggerFactory;
_eventBus = distributedEventBus;
}
public async Task PublishNotification(EventData evt)
{
await _eventBus.PublishAsync(evt);
}
public Task Start()
{
_subscriber = _eventBus.Subscribe(new LifeCycleEventHandler(
_loggerFactory.CreateLogger<LifeCycleEventHandler>()));
return Task.CompletedTask;
}
public Task Stop()
{
// TODO
_subscriber?.Dispose();
return Task.CompletedTask;
}
public void Subscribe(Action<EventData> action)
{
LifeCycleEventHandler.Subscribers.Add(action);
}
}
}

86
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.LifeCycleEvent/LINGYUN/Abp/WorkflowCore/LifeCycleEvent/AbpEventBusProvider.cs

@ -0,0 +1,86 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Json;
using WorkflowCore.Interface;
using EventData = WorkflowCore.Models.LifeCycleEvents.LifeCycleEvent;
namespace LINGYUN.Abp.WorkflowCore.LifeCycleEvent
{
public class AbpEventBusProvider : ILifeCycleEventHub
{
private bool _started = false;
private Queue<Action<EventData>> _deferredSubscribers = new Queue<Action<EventData>>();
private readonly IDistributedEventBus _eventBus;
private readonly ILoggerFactory _loggerFactory;
private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
ReferenceLoopHandling = ReferenceLoopHandling.Error,
};
public AbpEventBusProvider(
ILoggerFactory loggerFactory,
IDistributedEventBus distributedEventBus)
{
_loggerFactory = loggerFactory;
_eventBus = distributedEventBus;
}
public async Task PublishNotification(EventData evt)
{
var data = evt.SerializeObject(_serializerSettings);
var wrapEvent = new LifeCycleEventWrap(data);
await _eventBus.PublishAsync(wrapEvent);
}
public Task Start()
{
_started = true;
while (_deferredSubscribers.Count > 0)
{
var action = _deferredSubscribers.Dequeue();
_eventBus.Subscribe<LifeCycleEventWrap>((data) =>
{
var unWrapData = data.Data.DeserializeObject(_serializerSettings);
action(unWrapData as EventData);
return Task.CompletedTask;
});
}
return Task.CompletedTask;
}
public Task Stop()
{
// TODO
_started = false;
return Task.CompletedTask;
}
public void Subscribe(Action<EventData> action)
{
if (_started)
{
_eventBus.Subscribe<LifeCycleEventWrap>((data) =>
{
var unWrapData = data.Data.DeserializeObject(_serializerSettings);
action(unWrapData as EventData);
return Task.CompletedTask;
});
}
else
{
_deferredSubscribers.Enqueue(action);
}
}
}
}

22
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.LifeCycleEvent/LINGYUN/Abp/WorkflowCore/LifeCycleEvent/AbpWorkflowCoreLifeCycleEventModule.cs

@ -1,8 +1,11 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EventBus; using Volo.Abp.EventBus;
using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using WorkflowCore.Interface; using WorkflowCore.Interface;
using WorkflowCore.Models; using WorkflowCore.Models;
using EventData = WorkflowCore.Models.LifeCycleEvents.LifeCycleEvent;
namespace LINGYUN.Abp.WorkflowCore.LifeCycleEvent namespace LINGYUN.Abp.WorkflowCore.LifeCycleEvent
{ {
@ -12,12 +15,25 @@ namespace LINGYUN.Abp.WorkflowCore.LifeCycleEvent
{ {
public override void PreConfigureServices(ServiceConfigurationContext context) public override void PreConfigureServices(ServiceConfigurationContext context)
{ {
context.Services.AddSingleton<ILifeCycleEventHub, AbpEventBusLifeCycleEventHub>(); context.Services.AddSingleton<ILifeCycleEventHub, AbpEventBusProvider>();
context.Services.AddSingleton<AbpEventBusLifeCycleEventHub>(); context.Services.AddSingleton<AbpEventBusProvider>();
PreConfigure<WorkflowOptions>(options => PreConfigure<WorkflowOptions>(options =>
{ {
options.UseEventHub(provider => provider.GetRequiredService<AbpEventBusLifeCycleEventHub>()); options.UseEventHub(provider => provider.GetRequiredService<AbpEventBusProvider>());
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpJsonOptions>(options =>
{
options.UseHybridSerializer = true;
});
Configure<AbpSystemTextJsonSerializerOptions>(options =>
{
options.UnsupportedTypes.TryAdd<EventData>();
}); });
} }
} }

45
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.LifeCycleEvent/LINGYUN/Abp/WorkflowCore/LifeCycleEvent/LifeCycleEventHandler.cs

@ -1,45 +0,0 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.EventBus.Distributed;
using EventData = WorkflowCore.Models.LifeCycleEvents.LifeCycleEvent;
namespace LINGYUN.Abp.WorkflowCore.LifeCycleEvent
{
public class LifeCycleEventHandler : IDistributedEventHandler<EventData>
{
private readonly ILogger<LifeCycleEventHandler> _logger;
internal static readonly ICollection<Action<EventData>> Subscribers = new HashSet<Action<EventData>>();
public LifeCycleEventHandler(
ILogger<LifeCycleEventHandler> logger)
{
_logger = logger;
}
public Task HandleEventAsync(EventData eventData)
{
NotifySubscribers(eventData);
return Task.CompletedTask;
}
private void NotifySubscribers(EventData evt)
{
foreach (var subscriber in Subscribers)
{
try
{
subscriber(evt);
}
catch (Exception ex)
{
_logger.LogWarning(
default, ex, $"Error on event subscriber: {ex.Message}");
}
}
}
}
}

12
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.LifeCycleEvent/LINGYUN/Abp/WorkflowCore/LifeCycleEvent/LifeCycleEventWrap.cs

@ -0,0 +1,12 @@
namespace LINGYUN.Abp.WorkflowCore.LifeCycleEvent
{
public class LifeCycleEventWrap
{
public string Data { get; set; }
public LifeCycleEventWrap() { }
public LifeCycleEventWrap(string data)
{
Data = data;
}
}
}

47
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinition.cs

@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.WorkflowCore.Definitions
{
public class WorkflowDefinition : FullAuditedAggregateRoot<Guid>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
public string Title { get; protected set; }
public int Version { get; protected set; }
public string Description { get; protected set; }
public string Icon { get; protected set; }
public string Color { get; protected set; }
public string Group { get; protected set; }
public ICollection<WorkflowDefinitionNode> Nodes { get; protected set; }
public ICollection<WorkflowDefinitionFormData> Inputs { get; protected set; }
protected WorkflowDefinition()
{
Nodes = new Collection<WorkflowDefinitionNode>();
Inputs = new Collection<WorkflowDefinitionFormData>();
}
public WorkflowDefinition(
Guid id,
string title,
int version,
string group,
string icon,
string color,
string description = null,
Guid? tenantId = null) : base(id)
{
Title = title;
Version = version;
Group = group;
Icon = icon;
Color = color;
Description = description;
TenantId = tenantId;
Nodes = new Collection<WorkflowDefinitionNode>();
Inputs = new Collection<WorkflowDefinitionFormData>();
}
}
}

30
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinitionConditionCondition.cs

@ -1,30 +0,0 @@
using System;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.WorkflowCore.Definitions
{
public class WorkflowDefinitionConditionCondition : Entity<long>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
public virtual Guid ParentId { get; protected set; }
public virtual WorkflowDefinitionConditionNode ConditionNode { get; protected set; }
public virtual string Field { get; set; }
public virtual string Operator { get; set; }
public virtual string Value { get; set; }
protected WorkflowDefinitionConditionCondition() { }
public WorkflowDefinitionConditionCondition(
Guid parentId,
string field,
string opt,
string value,
Guid? tenantId = null)
{
ParentId = parentId;
Field = field;
Operator = opt;
Value = value;
TenantId = tenantId;
}
}
}

37
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinitionConditionNode.cs

@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.WorkflowCore.Definitions
{
public class WorkflowDefinitionConditionNode : Entity<long>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
public virtual Guid ParentId { get; protected set; }
public virtual WorkflowDefinitionNode Node { get; protected set; }
public virtual string Label { get; protected set; }
public virtual string NodeId { get; protected set; }
public virtual ICollection<WorkflowDefinitionConditionCondition> Conditions { get; protected set; }
protected WorkflowDefinitionConditionNode()
{
Conditions = new Collection<WorkflowDefinitionConditionCondition>();
}
public WorkflowDefinitionConditionNode(
Guid parentId,
string label,
string nodeId,
Guid? tenantId = null)
{
ParentId = parentId;
Label = label;
NodeId = nodeId;
TenantId = tenantId;
Conditions = new Collection<WorkflowDefinitionConditionCondition>();
}
}
}

10
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinitionExtensions.cs

@ -1,10 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace LINGYUN.Abp.WorkflowCore.Definitions
{
public class WorkflowDefinitionExtensions
{
}
}

52
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinitionFormData.cs

@ -1,52 +0,0 @@
using System;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.WorkflowCore.Definitions
{
public class WorkflowDefinitionFormData : Entity<long>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
public virtual Guid WorkflowId { get; protected set; }
public virtual WorkflowDefinition Workflow { get; protected set; }
public virtual string Name { get; protected set; }
public virtual string Label { get; protected set; }
public virtual string Type { get; protected set; }
public virtual string Value { get; protected set; }
public virtual ExtraPropertyDictionary Styles { get; protected set; }
public virtual int? MaxLength { get; protected set; }
public virtual int? MinLength { get; protected set; }
public virtual ExtraPropertyDictionary Items { get; protected set; }
public virtual ExtraPropertyDictionary Rules { get; protected set; }
protected WorkflowDefinitionFormData()
{
Styles = new ExtraPropertyDictionary();
Items = new ExtraPropertyDictionary();
Rules = new ExtraPropertyDictionary();
}
public WorkflowDefinitionFormData(
Guid workflowId,
string name,
string label,
string type,
string value,
int? minLength = null,
int? maxLength = null,
Guid? tenantId = null)
{
WorkflowId = workflowId;
Name = name;
Label = label;
Type = type;
Value = value;
MinLength = minLength;
MaxLength = maxLength;
TenantId = tenantId;
Styles = new ExtraPropertyDictionary();
Items = new ExtraPropertyDictionary();
Rules = new ExtraPropertyDictionary();
}
}
}

47
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinitionNode.cs

@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.WorkflowCore.Definitions
{
public class WorkflowDefinitionNode : Entity<long>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
public virtual Guid WorkflowId { get; protected set; }
public virtual WorkflowDefinition Workflow { get; protected set; }
public virtual string Key { get; protected set; }
public virtual string Title { get; protected set; }
public virtual string Position { get; protected set; }
public virtual string Type { get; protected set; }
public virtual WorkflowDefinitionStepBody StepBody { get; protected set; }
public virtual string ParentNodes { get; protected set; }
public virtual ICollection<WorkflowDefinitionConditionNode> NextNodes { get; protected set; }
protected WorkflowDefinitionNode()
{
NextNodes = new Collection<WorkflowDefinitionConditionNode>();
}
public WorkflowDefinitionNode(
Guid workflowId,
string key,
string title,
int[] position,
string type,
WorkflowDefinitionStepBody stepBody,
string[] parentNodes,
Guid? tenantId = null)
{
WorkflowId = workflowId;
Key = key;
Title = title;
Position = position.JoinAsString(";");
Type = type;
StepBody = stepBody;
ParentNodes = parentNodes.JoinAsString(";");
TenantId = tenantId;
NextNodes = new Collection<WorkflowDefinitionConditionNode>();
}
}
}

28
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Definitions/WorkflowDefinitionStepBody.cs

@ -1,28 +0,0 @@
using System;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.WorkflowCore.Definitions
{
public class WorkflowDefinitionStepBody : Entity<Guid>, IMultiTenant, IHasExtraProperties
{
public virtual Guid? TenantId { get; protected set; }
public virtual string Name { get; protected set; }
public ExtraPropertyDictionary ExtraProperties { get; protected set; }
protected WorkflowDefinitionStepBody()
{
ExtraProperties = new ExtraPropertyDictionary();
this.SetDefaultsForExtraProperties();
}
public WorkflowDefinitionStepBody(
Guid id,
string name) : base(id)
{
Name = name;
ExtraProperties = new ExtraPropertyDictionary();
this.SetDefaultsForExtraProperties();
}
}
}

15
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowCorePersistenceModule.cs

@ -1,9 +1,22 @@
using Volo.Abp.Modularity; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
using WorkflowCore.Interface;
using WorkflowCore.Models;
namespace LINGYUN.Abp.WorkflowCore.Persistence namespace LINGYUN.Abp.WorkflowCore.Persistence
{ {
[DependsOn(typeof(AbpWorkflowCoreModule))] [DependsOn(typeof(AbpWorkflowCoreModule))]
public class AbpWorkflowCorePersistenceModule : AbpModule public class AbpWorkflowCorePersistenceModule : AbpModule
{ {
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddSingleton<IPersistenceProvider, AbpWorkflowPersistenceProvider>();
context.Services.AddSingleton<AbpWorkflowPersistenceProvider>();
PreConfigure<WorkflowOptions>(options =>
{
options.UsePersistence(provider => provider.GetRequiredService<AbpWorkflowPersistenceProvider>());
});
}
} }
} }

2
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/WorkflowDbProperties.cs

@ -2,7 +2,7 @@
{ {
public static class WorkflowDbProperties public static class WorkflowDbProperties
{ {
public const string ConnectionStringName = "WorkflowCore"; public const string ConnectionStringName = "AbpWorkflowCore";
public static string TablePrefix = "WF_"; public static string TablePrefix = "WF_";
} }

11
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpRabbitMQWorkflowCoreOptions.cs

@ -7,9 +7,20 @@
/// </summary> /// </summary>
public string DefaultQueueNamePrefix { get; set; } public string DefaultQueueNamePrefix { get; set; }
/// <summary>
/// Default value: "AbpWorkflowCore".
/// </summary>
public string DefaultConnectionName { get; set; }
/// <summary>
/// Default valu: "AbpWorkflowCore"
/// </summary>
public string DefaultChannelName { get; set; }
public AbpRabbitMQWorkflowCoreOptions() public AbpRabbitMQWorkflowCoreOptions()
{ {
DefaultQueueNamePrefix = "AbpWorkflows."; DefaultQueueNamePrefix = "AbpWorkflows.";
DefaultConnectionName = "AbpWorkflowCore";
DefaultChannelName = "AbpWorkflowCore";
} }
} }
} }

47
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpRabbitMqQueueProvider.cs

@ -1,4 +1,6 @@
using Microsoft.Extensions.Options; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using RabbitMQ.Client; using RabbitMQ.Client;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@ -12,7 +14,6 @@ namespace LINGYUN.Abp.WorkflowCore.RabbitMQ
{ {
public class AbpRabbitMqQueueProvider : IQueueProvider public class AbpRabbitMqQueueProvider : IQueueProvider
{ {
private string ChannelPrefix = "WorkflowQueue.";
protected bool IsDiposed { get; private set; } protected bool IsDiposed { get; private set; }
protected SemaphoreSlim SyncObj = new SemaphoreSlim(1, 1); protected SemaphoreSlim SyncObj = new SemaphoreSlim(1, 1);
@ -21,7 +22,8 @@ namespace LINGYUN.Abp.WorkflowCore.RabbitMQ
protected IChannelPool ChannelPool { get; } protected IChannelPool ChannelPool { get; }
protected IQueueNameNormalizer QueueNameNormalizer { get; } protected IQueueNameNormalizer QueueNameNormalizer { get; }
protected AbpRabbitMQWorkflowCoreOptions RabbitMQWorkflowCoreOptions { get; } protected AbpRabbitMQWorkflowCoreOptions RabbitMQWorkflowCoreOptions { get; }
protected WorkflowQueueConfiguration QueueConfiguration { get; }
public ILogger<AbpRabbitMqQueueProvider> Logger { get; set; }
public bool IsDequeueBlocking => false; public bool IsDequeueBlocking => false;
@ -34,22 +36,17 @@ namespace LINGYUN.Abp.WorkflowCore.RabbitMQ
QueueNameNormalizer = queueNameNormalizer; QueueNameNormalizer = queueNameNormalizer;
RabbitMQWorkflowCoreOptions = options.Value; RabbitMQWorkflowCoreOptions = options.Value;
QueueConfiguration = GetOrCreateWorkflowQueueConfiguration(); Logger = NullLogger<AbpRabbitMqQueueProvider>.Instance;
}
protected virtual WorkflowQueueConfiguration GetOrCreateWorkflowQueueConfiguration()
{
return new WorkflowQueueConfiguration(
RabbitMQWorkflowCoreOptions.DefaultQueueNamePrefix + "Workflow-Core",
durable: true,
exclusive: false,
autoDelete: false);
} }
public async Task<string> DequeueWork(QueueType queue, CancellationToken cancellationToken) public async Task<string> DequeueWork(QueueType queue, CancellationToken cancellationToken)
{ {
CheckDisposed();
using (await SyncObj.LockAsync(cancellationToken)) using (await SyncObj.LockAsync(cancellationToken))
{ {
await EnsureInitializedAsync();
ChannelAccessor.Channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false); ChannelAccessor.Channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
var msg = ChannelAccessor.Channel.BasicGet(QueueNameNormalizer.NormalizeKey(queue), false); var msg = ChannelAccessor.Channel.BasicGet(QueueNameNormalizer.NormalizeKey(queue), false);
@ -65,8 +62,12 @@ namespace LINGYUN.Abp.WorkflowCore.RabbitMQ
public async Task QueueWork(string id, QueueType queue) public async Task QueueWork(string id, QueueType queue)
{ {
CheckDisposed();
using (await SyncObj.LockAsync()) using (await SyncObj.LockAsync())
{ {
await EnsureInitializedAsync();
var body = Encoding.UTF8.GetBytes(id); var body = Encoding.UTF8.GetBytes(id);
ChannelAccessor.Channel.BasicPublish( ChannelAccessor.Channel.BasicPublish(
@ -117,13 +118,29 @@ namespace LINGYUN.Abp.WorkflowCore.RabbitMQ
} }
ChannelAccessor = ChannelPool.Acquire( ChannelAccessor = ChannelPool.Acquire(
ChannelPrefix + QueueConfiguration.QueueName, RabbitMQWorkflowCoreOptions.DefaultChannelName,
QueueConfiguration.ConnectionName RabbitMQWorkflowCoreOptions.DefaultConnectionName
); );
CreateDeclareWorkflowQueue(QueueType.Event);
CreateDeclareWorkflowQueue(QueueType.Workflow);
CreateDeclareWorkflowQueue(QueueType.Index);
return Task.CompletedTask; return Task.CompletedTask;
} }
protected virtual void CreateDeclareWorkflowQueue(QueueType queue)
{
var queueName = QueueNameNormalizer.NormalizeKey(queue);
var configuration = new WorkflowQueueConfiguration(
queueName: queueName,
durable: true,
exclusive: false,
autoDelete: false);
configuration.Declare(ChannelAccessor.Channel);
}
protected void CheckDisposed() protected void CheckDisposed()
{ {
if (IsDiposed) if (IsDiposed)

8
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpWorkflowCoreRabbitMQModule.cs

@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.RabbitMQ; using Volo.Abp.RabbitMQ;
using WorkflowCore.Interface; using WorkflowCore.Interface;
@ -20,5 +21,12 @@ namespace LINGYUN.Abp.WorkflowCore.RabbitMQ
options.UseQueueProvider(provider => provider.GetRequiredService<AbpRabbitMqQueueProvider>()); options.UseQueueProvider(provider => provider.GetRequiredService<AbpRabbitMqQueueProvider>());
}); });
} }
public override void OnApplicationShutdown(ApplicationShutdownContext context)
{
context.ServiceProvider
.GetRequiredService<AbpRabbitMqQueueProvider>()
.Dispose();
}
} }
} }

17
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/QueueNameNormalizer.cs

@ -1,20 +1,29 @@
using Volo.Abp.DependencyInjection; using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using WorkflowCore.Interface; using WorkflowCore.Interface;
namespace LINGYUN.Abp.WorkflowCore.RabbitMQ namespace LINGYUN.Abp.WorkflowCore.RabbitMQ
{ {
public class QueueNameNormalizer : IQueueNameNormalizer, ISingletonDependency public class QueueNameNormalizer : IQueueNameNormalizer, ISingletonDependency
{ {
protected AbpRabbitMQWorkflowCoreOptions RabbitMQWorkflowCoreOptions { get; }
public QueueNameNormalizer(
IOptions<AbpRabbitMQWorkflowCoreOptions> options)
{
RabbitMQWorkflowCoreOptions = options.Value;
}
public string NormalizeKey(QueueType queue) public string NormalizeKey(QueueType queue)
{ {
switch (queue) switch (queue)
{ {
case QueueType.Workflow: case QueueType.Workflow:
return "wfc.workflow_queue"; return RabbitMQWorkflowCoreOptions.DefaultQueueNamePrefix + "wfc.workflow_queue";
case QueueType.Event: case QueueType.Event:
return "wfc.event_queue"; return RabbitMQWorkflowCoreOptions.DefaultQueueNamePrefix + "wfc.event_queue";
case QueueType.Index: case QueueType.Index:
return "wfc.index_queue"; return RabbitMQWorkflowCoreOptions.DefaultQueueNamePrefix + "wfc.index_queue";
default: default:
return null; return null;
} }

4
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/WorkflowQueueConfiguration.cs

@ -4,18 +4,14 @@ namespace LINGYUN.Abp.WorkflowCore.RabbitMQ
{ {
public class WorkflowQueueConfiguration : QueueDeclareConfiguration public class WorkflowQueueConfiguration : QueueDeclareConfiguration
{ {
public string ConnectionName { get; set; }
public WorkflowQueueConfiguration( public WorkflowQueueConfiguration(
string queueName, string queueName,
string connectionName = null,
bool durable = true, bool durable = true,
bool exclusive = false, bool exclusive = false,
bool autoDelete = false, bool autoDelete = false,
string deadLetterQueueName = null) string deadLetterQueueName = null)
: base(queueName, durable, exclusive, autoDelete, deadLetterQueueName) : base(queueName, durable, exclusive, autoDelete, deadLetterQueueName)
{ {
ConnectionName = connectionName;
} }
} }
} }

9
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpWorkflowCoreModule.cs

@ -1,8 +1,10 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Volo.Abp;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using WorkflowCore.Interface; using WorkflowCore.Interface;
using WorkflowCore.Services;
namespace LINGYUN.Abp.WorkflowCore namespace LINGYUN.Abp.WorkflowCore
{ {
@ -22,23 +24,24 @@ namespace LINGYUN.Abp.WorkflowCore
context.Services.ExecutePreConfiguredActions(options); context.Services.ExecutePreConfiguredActions(options);
}); });
context.Services.AddWorkflowDSL(); context.Services.AddWorkflowDSL();
//context.Services.AddHostedService((provider) => provider.GetRequiredService<IWorkflowHost>());
} }
public override void OnApplicationInitialization(Volo.Abp.ApplicationInitializationContext context) public override void OnApplicationInitialization(ApplicationInitializationContext context)
{ {
var workflowRegistry = context.ServiceProvider.GetRequiredService<IWorkflowRegistry>(); var workflowRegistry = context.ServiceProvider.GetRequiredService<IWorkflowRegistry>();
foreach (var definitionWorkflow in _definitionWorkflows) foreach (var definitionWorkflow in _definitionWorkflows)
{ {
var workflow = context.ServiceProvider.GetRequiredService(definitionWorkflow); var workflow = context.ServiceProvider.GetRequiredService(definitionWorkflow);
workflowRegistry.RegisterWorkflow(workflow as IWorkflow<WorkflowParamDictionary>); workflowRegistry.RegisterWorkflow(workflow as WorkflowBase);
} }
var workflowHost = context.ServiceProvider.GetRequiredService<IWorkflowHost>(); var workflowHost = context.ServiceProvider.GetRequiredService<IWorkflowHost>();
workflowHost.Start(); workflowHost.Start();
} }
public override void OnApplicationShutdown(Volo.Abp.ApplicationShutdownContext context) public override void OnApplicationShutdown(ApplicationShutdownContext context)
{ {
var workflowHost = context.ServiceProvider.GetRequiredService<IWorkflowHost>(); var workflowHost = context.ServiceProvider.GetRequiredService<IWorkflowHost>();
workflowHost.Stop(); workflowHost.Stop();

8
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowBase.cs

@ -1,14 +1,14 @@
using WorkflowCore.Interface; using Volo.Abp.DependencyInjection;
using Volo.Abp.DependencyInjection; using WorkflowCore.Interface;
namespace LINGYUN.Abp.WorkflowCore namespace LINGYUN.Abp.WorkflowCore
{ {
public abstract class WorkflowBase : IWorkflow<WorkflowParamDictionary>, ISingletonDependency public abstract class WorkflowBase : IWorkflow, ISingletonDependency
{ {
public abstract string Id { get; } public abstract string Id { get; }
public abstract int Version { get; } public abstract int Version { get; }
public abstract void Build(IWorkflowBuilder<WorkflowParamDictionary> builder); public abstract void Build(IWorkflowBuilder<object> builder);
} }
} }

9
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowConditionCondition.cs

@ -1,9 +0,0 @@
namespace LINGYUN.Abp.WorkflowCore
{
public class WorkflowConditionCondition
{
public string Field { get; set; }
public string Operator { get; set; }
public object Value { get; set; }
}
}

15
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowConditionNode.cs

@ -1,15 +0,0 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.WorkflowCore
{
public class WorkflowConditionNode
{
public string Label { get; set; }
public string NodeId { get; set; }
public IEnumerable<WorkflowConditionCondition> Conditions { get; set; }
public WorkflowConditionNode()
{
Conditions = new List<WorkflowConditionCondition>();
}
}
}

18
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowDefine.cs

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
namespace LINGYUN.Abp.WorkflowCore
{
public class WorkflowDefine
{
public string Id { get; set; }
public int Version { get; set; }
public string Name { get; set; }
public Type DataType { get; set; }
public List<WorkflowStepBody> Steps { get; set; }
public WorkflowDefine()
{
Steps = new List<WorkflowStepBody>();
}
}
}

17
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowDefinition.cs

@ -1,17 +0,0 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.WorkflowCore
{
public class WorkflowDefinition
{
public string Id { get; set; }
public string Title { get; set; }
public int Version { get; set; }
public string Description { get; set; }
public string Icon { get; set; }
public string Color { get; set; }
public string Group { get; set; }
public ICollection<WorkflowNode> Nodes { get; set; }
public ICollection<WorkflowFormData> Inputs { get; set; }
}
}

24
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowFormData.cs

@ -1,24 +0,0 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.WorkflowCore
{
public class WorkflowFormData
{
public string Id { get; set; }
public string Name { get; set; }
public string Label { get; set; }
public string Type { get; set; }
public object Value { get; set; }
public IEnumerable<object> Styles { get; set; }
public int? MaxLength { get; set; }
public int? MinLength { get; set; }
public IEnumerable<object> Items { get; set; }
public IEnumerable<object> Rules { get; set; }
public WorkflowFormData()
{
Styles = new List<object>();
Items = new List<object>();
Rules =new List<object>();
}
}
}

105
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowManager.cs

@ -1,105 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Volo.Abp;
using WorkflowCore.Interface;
using WorkflowCore.Models.DefinitionStorage.v1;
using WorkflowCore.Services.DefinitionStorage;
using WDF = WorkflowCore.Models.WorkflowDefinition;
namespace LINGYUN.Abp.WorkflowCore
{
public class WorkflowManager : IWorkflowManager
{
private readonly IWorkflowRegistry _workflowRegistry;
private readonly IDefinitionLoader _definitionLoader;
protected IReadOnlyCollection<WorkflowStepBody> _stepBodys;
internal void Initlize()
{
}
public WDF BuildWorkflow(WorkflowDefinition definition)
{
if (_workflowRegistry.IsRegistered(definition.Id, definition.Version))
{
throw new AbpException($"Workflow {definition.Id} has ben registered!");
}
var definitionSource = new DefinitionSourceV1()
{
Id = definition.Id,
Version = definition.Version,
DataType = $"{typeof(Dictionary<string, object>).FullName}, {typeof(Dictionary<string, object>).Assembly.FullName}",
Description = definition.Title,
};
BuildWorkflow(definition.Nodes, definitionSource, _stepBodys, definition.Nodes.First(u => u.Key.ToLower().StartsWith("start")));
var json = definitionSource.SerializeObject();
var def = _definitionLoader.LoadDefinition(json, Deserializers.Json);
return def;
}
protected virtual void BuildWorkflow(IEnumerable<WorkflowNode> allNodes, DefinitionSourceV1 source, IEnumerable<WorkflowStepBody> stepBodys, WorkflowNode node)
{
if (source.Steps.Any(u => u.Id == node.Key))
{
return;
}
var stepSource = new StepSourceV1
{
Id = node.Key,
Name = node.Key
};
WorkflowStepBody stepbody = stepBodys.FirstOrDefault(u => u.Name == node.StepBody.Name);
if (stepbody == null)
{
stepbody = new WorkflowStepBody() { StepBodyType = typeof(NullStepBody) };
}
stepSource.StepType = $"{stepbody.StepBodyType.FullName}, {stepbody.StepBodyType.Assembly.FullName}";
foreach (var input in stepbody.Inputs)
{
var value = node.StepBody.Inputs[input.Key].Value;
if (!(value is IDictionary<string, object> || value is IDictionary<object, object>))
{
value = $"\"{value}\"";
}
stepSource.Inputs.AddIfNotContains(new KeyValuePair<string, object>(input.Key, value));
}
source.Steps.Add(stepSource);
BuildBranching(allNodes, source, stepSource, stepBodys, node.NextNodes);
}
protected virtual void BuildBranching(IEnumerable<WorkflowNode> allNodes, DefinitionSourceV1 source, StepSourceV1 stepSource, IEnumerable<WorkflowStepBody> stepBodys, IEnumerable<WorkflowConditionNode> nodes)
{
foreach (var nextNode in nodes)
{
var node = allNodes.First(u => u.Key == nextNode.NodeId);
stepSource.SelectNextStep[nextNode.NodeId] = "1==1";
if (nextNode.Conditions.Count() > 0)
{
List<string> exps = new List<string>();
foreach (var cond in nextNode.Conditions)
{
if (cond.Value is string && (!decimal.TryParse(cond.Value.ToString(), out decimal tempValue)))
{
if (cond.Operator != "==" && cond.Operator != "!=")
{
throw new AbpException($" if {cond.Field} is type of 'String', the Operator must be \"==\" or \"!=\"");
}
exps.Add($"data[\"{cond.Field}\"].ToString() {cond.Operator} \"{cond.Value}\"");
continue;
}
exps.Add($"decimal.Parse(data[\"{cond.Field}\"].ToString()) {cond.Operator} {cond.Value}");
}
stepSource.SelectNextStep[nextNode.NodeId] = string.Join(" && ", exps);
}
BuildWorkflow(allNodes, source, stepBodys, node);
}
}
}
}

20
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowNode.cs

@ -1,20 +0,0 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.WorkflowCore
{
public class WorkflowNode
{
public string Key { get; set; }
public string Title { get; set; }
public int[] Position { get; set; }
public string Type { get; set; }
public WorkflowStepBody StepBody { get; set; }
public IEnumerable<string> ParentNodes { get; set; }
public IEnumerable<WorkflowConditionNode> NextNodes { get; set; }
public WorkflowNode()
{
StepBody = new WorkflowStepBody();
NextNodes = new List<WorkflowConditionNode>();
}
}
}

10
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowParam.cs

@ -1,10 +0,0 @@
namespace LINGYUN.Abp.WorkflowCore
{
public class WorkflowParam
{
public string Name { get; set; }
public string DisplayName { get; set; }
public string InputType { get; set; }
public object Value { get; set; }
}
}

8
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowParamDictionary.cs

@ -1,8 +0,0 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.WorkflowCore
{
public class WorkflowParamDictionary : Dictionary<string, WorkflowParam>
{
}
}

8
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowParamInput.cs

@ -1,8 +0,0 @@
namespace LINGYUN.Abp.WorkflowCore
{
public class WorkflowParamInput
{
public string Name { get; set; }
public object Value { get; set; }
}
}

20
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/WorkflowStepBody.cs

@ -1,17 +1,31 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using WorkflowCore.Models;
namespace LINGYUN.Abp.WorkflowCore namespace LINGYUN.Abp.WorkflowCore
{ {
public class WorkflowStepBody public class WorkflowStepBody
{ {
public string Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
public Type StepBodyType { get; set; } public Type StepType { get; set; }
public bool Saga { get; set; }
public string DisplayName { get; set; } public string DisplayName { get; set; }
public Dictionary<string, WorkflowParamInput> Inputs { get; set; } public string NextStep { get; set; }
public string CancelCondition { get; set; }
public TimeSpan? RetryInterval { get; set; }
public WorkflowErrorHandling? ErrorBehavior { get; set; }
public List<WorkflowStepBody> CompensateWith { get; set; }
public Dictionary<string, object> Inputs { get; set; }
public Dictionary<string, object> Outputs { get; set; }
public Dictionary<string, object> SelectNextStep { get; set; }
public WorkflowStepBody() public WorkflowStepBody()
{ {
Inputs = new Dictionary<string, WorkflowParamInput>(); CompensateWith = new List<WorkflowStepBody>();
Inputs = new Dictionary<string, object>();
Outputs = new Dictionary<string, object>();
SelectNextStep = new Dictionary<string, object>();
} }
} }
} }

8
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/System/ObjectSerializerExtensions.cs

@ -6,14 +6,14 @@ namespace System
{ {
private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All };
public static string SerializeObject(this object obj) public static string SerializeObject(this object obj, JsonSerializerSettings serializerSettings = null)
{ {
return JsonConvert.SerializeObject(obj, SerializerSettings); return JsonConvert.SerializeObject(obj, serializerSettings ?? SerializerSettings);
} }
public static object DeserializeObject(this string str) public static object DeserializeObject(this string str, JsonSerializerSettings serializerSettings = null)
{ {
return JsonConvert.DeserializeObject(str, SerializerSettings); return JsonConvert.DeserializeObject(str, serializerSettings ?? SerializerSettings);
} }
} }
} }

1
aspnet-core/tests/LINGYUN.Abp.WorkflowCore.Tests/LINGYUN.Abp.WorkflowCore.Tests.csproj

@ -11,6 +11,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\modules\workflow\LINGYUN.Abp.WorkflowCore\LINGYUN.Abp.WorkflowCore.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj" /> <ProjectReference Include="..\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj" />
</ItemGroup> </ItemGroup>

Loading…
Cancel
Save