mirror of https://github.com/abpframework/abp.git
Browse Source
Centralize and simplify anonymous event handling across transports. Introduces AnonymousEventDataConverter and changes AnonymousEventData to store optional JsonData with a FromJson factory. Adds helpers (CreateAnonymousEnvelope, TryPublishTypedByEventNameAsync, TryResolveStoredEventData, TryResolveIncomingEvent) and unifies handling logic in Dapr/Azure/Kafka/RabbitMQ/Rebus implementations. Also deduplicates subscription registration using locking, cleans up empty anonymous handler maps, and removes duplicated JSON conversion code. Tests updated to match the new anonymous event semantics.pull/25023/head
14 changed files with 1261 additions and 506 deletions
@ -0,0 +1,95 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text.Json; |
||||
|
|
||||
|
namespace Volo.Abp.EventBus; |
||||
|
|
||||
|
public static class AnonymousEventDataConverter |
||||
|
{ |
||||
|
public static T ConvertToTypedObject<T>(AnonymousEventData eventData) |
||||
|
{ |
||||
|
if (eventData.Data is T typedData) |
||||
|
{ |
||||
|
return typedData; |
||||
|
} |
||||
|
|
||||
|
return ParseJsonElement(eventData).Deserialize<T>() |
||||
|
?? throw new InvalidOperationException($"Failed to deserialize AnonymousEventData to {typeof(T).FullName}."); |
||||
|
} |
||||
|
|
||||
|
public static object ConvertToTypedObject(AnonymousEventData eventData, Type type) |
||||
|
{ |
||||
|
if (type.IsInstanceOfType(eventData.Data)) |
||||
|
{ |
||||
|
return eventData.Data; |
||||
|
} |
||||
|
|
||||
|
return ParseJsonElement(eventData).Deserialize(type) |
||||
|
?? throw new InvalidOperationException($"Failed to deserialize AnonymousEventData to {type.FullName}."); |
||||
|
} |
||||
|
|
||||
|
public static object ConvertToLooseObject(AnonymousEventData eventData) |
||||
|
{ |
||||
|
return ConvertElement(ParseJsonElement(eventData)); |
||||
|
} |
||||
|
|
||||
|
public static string GetJsonData(AnonymousEventData eventData) |
||||
|
{ |
||||
|
return eventData.JsonData ?? ParseJsonElement(eventData).GetRawText(); |
||||
|
} |
||||
|
|
||||
|
private static JsonElement ParseJsonElement(AnonymousEventData eventData) |
||||
|
{ |
||||
|
if (eventData.Data is JsonElement existingElement) |
||||
|
{ |
||||
|
return existingElement; |
||||
|
} |
||||
|
|
||||
|
if (eventData.JsonData != null) |
||||
|
{ |
||||
|
return JsonDocument.Parse(eventData.JsonData).RootElement.Clone(); |
||||
|
} |
||||
|
|
||||
|
return JsonSerializer.SerializeToElement(eventData.Data); |
||||
|
} |
||||
|
|
||||
|
private static object ConvertElement(JsonElement element) |
||||
|
{ |
||||
|
switch (element.ValueKind) |
||||
|
{ |
||||
|
case JsonValueKind.Object: |
||||
|
{ |
||||
|
var obj = new Dictionary<string, object?>(); |
||||
|
foreach (var property in element.EnumerateObject()) |
||||
|
{ |
||||
|
obj[property.Name] = property.Value.ValueKind == JsonValueKind.Null |
||||
|
? null |
||||
|
: ConvertElement(property.Value); |
||||
|
} |
||||
|
|
||||
|
return obj; |
||||
|
} |
||||
|
case JsonValueKind.Array: |
||||
|
return element.EnumerateArray() |
||||
|
.Select(item => item.ValueKind == JsonValueKind.Null ? null : (object?)ConvertElement(item)) |
||||
|
.ToList(); |
||||
|
case JsonValueKind.String: |
||||
|
return element.GetString()!; |
||||
|
case JsonValueKind.Number when element.TryGetInt64(out var longValue): |
||||
|
return longValue; |
||||
|
case JsonValueKind.Number when element.TryGetDecimal(out var decimalValue): |
||||
|
return decimalValue; |
||||
|
case JsonValueKind.Number when element.TryGetDouble(out var doubleValue): |
||||
|
return doubleValue; |
||||
|
case JsonValueKind.True: |
||||
|
return true; |
||||
|
case JsonValueKind.False: |
||||
|
return false; |
||||
|
case JsonValueKind.Null: |
||||
|
case JsonValueKind.Undefined: |
||||
|
default: |
||||
|
return null!; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue