Merge pull request #387 from iceljc/features/refine-conv-states
Features/refine conv states
This commit is contained in:
commit
3b248c3d6b
|
|
@ -22,6 +22,7 @@
|
|||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
namespace BotSharp.Abstraction.Conversations.Enums;
|
||||
|
||||
public class StateDataType
|
||||
{
|
||||
public const string String = "string";
|
||||
public const string Boolean = "boolean";
|
||||
public const string Number = "number";
|
||||
public const string Currency = "currency";
|
||||
public const string Date = "date";
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
namespace BotSharp.Abstraction.Conversations.Enums;
|
||||
|
||||
public class StateSource
|
||||
{
|
||||
public const string External = "external";
|
||||
public const string Application = "application";
|
||||
public const string User = "user";
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Conversations.Enums;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace BotSharp.Abstraction.Conversations;
|
||||
|
|
@ -12,7 +13,8 @@ public interface IConversationStateService
|
|||
string GetState(string name, string defaultValue = "");
|
||||
bool ContainsState(string name);
|
||||
Dictionary<string, string> GetStates();
|
||||
IConversationStateService SetState<T>(string name, T value, bool isNeedVersion = true, int activeRounds = -1);
|
||||
IConversationStateService SetState<T>(string name, T value, bool isNeedVersion = true,
|
||||
int activeRounds = -1, string valueType = StateDataType.String, string source = StateSource.User, bool readOnly = false);
|
||||
void SaveStateByArgs(JsonDocument args);
|
||||
void CleanStates();
|
||||
void Save();
|
||||
|
|
|
|||
|
|
@ -22,4 +22,13 @@ public class StateChangeModel
|
|||
|
||||
[JsonPropertyName("after_active_rounds")]
|
||||
public int? AfterActiveRounds { get; set; }
|
||||
|
||||
[JsonPropertyName("data_type")]
|
||||
public string DataType { get; set; }
|
||||
|
||||
[JsonPropertyName("source")]
|
||||
public string Source { get; set; }
|
||||
|
||||
[JsonPropertyName("readonly")]
|
||||
public bool Readonly { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
using BotSharp.Abstraction.Conversations.Enums;
|
||||
|
||||
namespace BotSharp.Abstraction.Conversations.Models;
|
||||
|
||||
public class StateKeyValue
|
||||
{
|
||||
public string Key { get; set; }
|
||||
public bool Versioning { get; set; }
|
||||
public bool Readonly { get; set; }
|
||||
public List<StateValue> Values { get; set; } = new List<StateValue>();
|
||||
|
||||
public StateKeyValue()
|
||||
|
|
@ -16,6 +19,12 @@ public class StateKeyValue
|
|||
Key = key;
|
||||
Values = values;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var lastValue = Values.LastOrDefault();
|
||||
return $"{Key} => ({lastValue?.ToString()})";
|
||||
}
|
||||
}
|
||||
|
||||
public class StateValue
|
||||
|
|
@ -30,6 +39,12 @@ public class StateValue
|
|||
[JsonPropertyName("active_rounds")]
|
||||
public int ActiveRounds { get; set; }
|
||||
|
||||
[JsonPropertyName("data_type")]
|
||||
public string DataType { get; set; } = StateDataType.String;
|
||||
|
||||
[JsonPropertyName("source")]
|
||||
public string Source { get; set; }
|
||||
|
||||
[JsonPropertyName("update_time")]
|
||||
public DateTime UpdateTime { get; set; }
|
||||
|
||||
|
|
@ -37,4 +52,11 @@ public class StateValue
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var isActive = Active ? "Yes" : "No";
|
||||
var activeRounds = ActiveRounds <= 0 ? "infinity" : ActiveRounds.ToString();
|
||||
return $"Data: {Data}, Active: {isActive}, Active rounds: {activeRounds}, Source: {Source}";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,19 @@
|
|||
using BotSharp.Abstraction.Messaging;
|
||||
using BotSharp.Abstraction.Messaging.Enums;
|
||||
using BotSharp.Abstraction.Messaging.Models.RichContent.Template;
|
||||
using BotSharp.Abstraction.Messaging.Models.RichContent;
|
||||
using System.Text.Json;
|
||||
using System.Reflection;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BotSharp.Core.Messaging;
|
||||
namespace BotSharp.Abstraction.Messaging;
|
||||
|
||||
public static class MessageParser
|
||||
public static class BotSharpMessageParser
|
||||
{
|
||||
|
||||
public static IRichMessage? ParseRichMessage(JsonElement root, JsonSerializerOptions options)
|
||||
public static IRichMessage? ParseRichMessage(JsonElement root)
|
||||
{
|
||||
IRichMessage? res = null;
|
||||
Type? targetType = null;
|
||||
JsonElement element;
|
||||
var jsonText = root.GetRawText();
|
||||
|
||||
|
|
@ -20,47 +22,52 @@ public static class MessageParser
|
|||
var richType = element.GetString();
|
||||
if (richType == RichTypeEnum.ButtonTemplate)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<ButtonTemplateMessage>(jsonText, options);
|
||||
targetType = typeof(ButtonTemplateMessage);
|
||||
}
|
||||
else if (richType == RichTypeEnum.MultiSelectTemplate)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<MultiSelectTemplateMessage>(jsonText, options);
|
||||
targetType = typeof(MultiSelectTemplateMessage);
|
||||
}
|
||||
else if (richType == RichTypeEnum.QuickReply)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<QuickReplyMessage>(jsonText, options);
|
||||
targetType = typeof(QuickReplyMessage);
|
||||
}
|
||||
else if (richType == RichTypeEnum.CouponTemplate)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<CouponTemplateMessage>(jsonText, options);
|
||||
targetType = typeof(CouponTemplateMessage);
|
||||
}
|
||||
else if (richType == RichTypeEnum.Text)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<TextMessage>(jsonText, options);
|
||||
targetType = typeof(TextMessage);
|
||||
}
|
||||
else if (richType == RichTypeEnum.GenericTemplate)
|
||||
{
|
||||
if (root.TryGetProperty("element_type", out element))
|
||||
{
|
||||
var elementType = element.GetString();
|
||||
if (elementType == typeof(GenericElement).Name)
|
||||
var wrapperType = typeof(GenericTemplateMessage<>);
|
||||
var genericType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.Name == elementType);
|
||||
|
||||
if (wrapperType != null && genericType != null)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<GenericTemplateMessage<GenericElement>>(jsonText, options);
|
||||
}
|
||||
else if (elementType == typeof(ButtonElement).Name)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<GenericTemplateMessage<ButtonElement>>(jsonText, options);
|
||||
targetType = wrapperType.MakeGenericType(genericType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetType != null)
|
||||
{
|
||||
res = JsonConvert.DeserializeObject(jsonText, targetType) as IRichMessage;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static ITemplateMessage? ParseTemplateMessage(JsonElement root, JsonSerializerOptions options)
|
||||
public static ITemplateMessage? ParseTemplateMessage(JsonElement root)
|
||||
{
|
||||
ITemplateMessage? res = null;
|
||||
Type? targetType = null;
|
||||
JsonElement element;
|
||||
var jsonText = root.GetRawText();
|
||||
|
||||
|
|
@ -69,37 +76,42 @@ public static class MessageParser
|
|||
var templateType = element.GetString();
|
||||
if (templateType == TemplateTypeEnum.Button)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<ButtonTemplateMessage>(jsonText, options);
|
||||
targetType = typeof(ButtonTemplateMessage);
|
||||
}
|
||||
else if (templateType == TemplateTypeEnum.MultiSelect)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<MultiSelectTemplateMessage>(jsonText, options);
|
||||
targetType = typeof(MultiSelectTemplateMessage);
|
||||
}
|
||||
else if (templateType == TemplateTypeEnum.Coupon)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<CouponTemplateMessage>(jsonText, options);
|
||||
targetType = typeof(CouponTemplateMessage);
|
||||
}
|
||||
else if (templateType == TemplateTypeEnum.Product)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<ProductTemplateMessage>(jsonText, options);
|
||||
targetType = typeof(ProductTemplateMessage);
|
||||
}
|
||||
else if (templateType == TemplateTypeEnum.Generic)
|
||||
{
|
||||
if (root.TryGetProperty("element_type", out element))
|
||||
{
|
||||
var elementType = element.GetString();
|
||||
if (elementType == typeof(GenericElement).Name)
|
||||
var wrapperType = typeof(GenericTemplateMessage<>);
|
||||
var genericType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.Name == elementType);
|
||||
|
||||
if (wrapperType != null && genericType != null)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<GenericTemplateMessage<GenericElement>>(jsonText, options);
|
||||
}
|
||||
else if (elementType == typeof(ButtonElement).Name)
|
||||
{
|
||||
res = JsonSerializer.Deserialize<GenericTemplateMessage<ButtonElement>>(jsonText, options);
|
||||
targetType = wrapperType.MakeGenericType(genericType);
|
||||
res = JsonConvert.DeserializeObject(jsonText, targetType) as ITemplateMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetType != null)
|
||||
{
|
||||
res = JsonConvert.DeserializeObject(jsonText, targetType) as ITemplateMessage;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
using BotSharp.Core.Messaging;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace BotSharp.Abstraction.Messaging.JsonConverters;
|
||||
|
|
@ -9,8 +8,7 @@ public class RichContentJsonConverter : JsonConverter<IRichMessage>
|
|||
{
|
||||
using var jsonDoc = JsonDocument.ParseValue(ref reader);
|
||||
var root = jsonDoc.RootElement;
|
||||
var jsonText = root.GetRawText();
|
||||
var res = MessageParser.ParseRichMessage(root, options);
|
||||
var res = BotSharpMessageParser.ParseRichMessage(root);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using BotSharp.Core.Messaging;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace BotSharp.Abstraction.Messaging.JsonConverters;
|
||||
|
|
@ -9,8 +8,7 @@ public class TemplateMessageJsonConverter : JsonConverter<ITemplateMessage>
|
|||
{
|
||||
using var jsonDoc = JsonDocument.ParseValue(ref reader);
|
||||
var root = jsonDoc.RootElement;
|
||||
var jsonText = root.GetRawText();
|
||||
var res = MessageParser.ParseTemplateMessage(root, options);
|
||||
var res = BotSharpMessageParser.ParseTemplateMessage(root);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,19 @@ namespace BotSharp.Abstraction.Messaging.Models.RichContent;
|
|||
/// </summary>
|
||||
public class ElementButton
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public string Type { get; set; } = "web_url";
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string Url { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string Payload { get; set; }
|
||||
|
||||
[JsonPropertyName("is_primary")]
|
||||
public bool IsPrimary { get; set; }
|
||||
|
||||
[JsonPropertyName("is_secondary")]
|
||||
public bool IsSecondary { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,27 +17,8 @@ public class ButtonTemplateMessage : IRichMessage, ITemplateMessage
|
|||
public string TemplateType => TemplateTypeEnum.Button;
|
||||
|
||||
[JsonPropertyName("buttons")]
|
||||
public ButtonElement[] Buttons { get; set; } = new ButtonElement[0];
|
||||
public ElementButton[] Buttons { get; set; } = new ElementButton[0];
|
||||
|
||||
[JsonPropertyName("is_horizontal")]
|
||||
public bool IsHorizontal { get; set; }
|
||||
}
|
||||
|
||||
public class ButtonElement
|
||||
{
|
||||
/// <summary>
|
||||
/// web_url, postback, phone_number
|
||||
/// </summary>
|
||||
public string Type { get; set; } = "web_url";
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? Url { get; set; }
|
||||
|
||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string? Payload { get; set; }
|
||||
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("is_primary")]
|
||||
public bool IsPrimary { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Conversations.Enums;
|
||||
using BotSharp.Abstraction.Models;
|
||||
|
||||
namespace BotSharp.Core.Conversations.Services;
|
||||
|
|
@ -126,6 +127,6 @@ public partial class ConversationService : IConversationService
|
|||
{
|
||||
_conversationId = conversationId;
|
||||
_state.Load(_conversationId);
|
||||
states.ForEach(x => _state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds));
|
||||
states.ForEach(x => _state.SetState(x.Key, x.Value, activeRounds: x.ActiveRounds, source: StateSource.External));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Conversations.Enums;
|
||||
using BotSharp.Abstraction.Users.Enums;
|
||||
|
||||
namespace BotSharp.Core.Conversations.Services;
|
||||
|
|
@ -33,7 +34,8 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
/// <param name="value"></param>
|
||||
/// <param name="isNeedVersion">whether the state is related to message or not</param>
|
||||
/// <returns></returns>
|
||||
public IConversationStateService SetState<T>(string name, T value, bool isNeedVersion = true, int activeRounds = -1)
|
||||
public IConversationStateService SetState<T>(string name, T value, bool isNeedVersion = true,
|
||||
int activeRounds = -1, string valueType = StateDataType.String, string source = StateSource.User, bool readOnly = false)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
|
|
@ -56,24 +58,31 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
_logger.LogInformation($"[STATE] {name} = {value}");
|
||||
var routingCtx = _services.GetRequiredService<IRoutingContext>();
|
||||
|
||||
foreach (var hook in hooks)
|
||||
if (!ContainsState(name) || preValue != currentValue || preActiveRounds != curActiveRounds)
|
||||
{
|
||||
hook.OnStateChanged(new StateChangeModel
|
||||
foreach (var hook in hooks)
|
||||
{
|
||||
ConversationId = _conversationId,
|
||||
MessageId = routingCtx.MessageId,
|
||||
Name = name,
|
||||
BeforeValue = preValue,
|
||||
BeforeActiveRounds = preActiveRounds,
|
||||
AfterValue = currentValue,
|
||||
AfterActiveRounds = curActiveRounds
|
||||
}).Wait();
|
||||
hook.OnStateChanged(new StateChangeModel
|
||||
{
|
||||
ConversationId = _conversationId,
|
||||
MessageId = routingCtx.MessageId,
|
||||
Name = name,
|
||||
BeforeValue = preValue,
|
||||
BeforeActiveRounds = preActiveRounds,
|
||||
AfterValue = currentValue,
|
||||
AfterActiveRounds = curActiveRounds,
|
||||
DataType = valueType,
|
||||
Source = source,
|
||||
Readonly = readOnly
|
||||
}).Wait();
|
||||
}
|
||||
}
|
||||
|
||||
var newPair = new StateKeyValue
|
||||
{
|
||||
Key = name,
|
||||
Versioning = isNeedVersion
|
||||
Versioning = isNeedVersion,
|
||||
Readonly = readOnly
|
||||
};
|
||||
|
||||
var newValue = new StateValue
|
||||
|
|
@ -82,6 +91,8 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
MessageId = routingCtx.MessageId,
|
||||
Active = true,
|
||||
ActiveRounds = curActiveRounds,
|
||||
DataType = valueType,
|
||||
Source = source,
|
||||
UpdateTime = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
|
|
@ -132,6 +143,8 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
MessageId = curMsgId,
|
||||
Active = false,
|
||||
ActiveRounds = value.ActiveRounds,
|
||||
DataType = value.DataType,
|
||||
Source = value.Source,
|
||||
UpdateTime = DateTime.UtcNow
|
||||
});
|
||||
continue;
|
||||
|
|
@ -192,6 +205,8 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
MessageId = curMsgId,
|
||||
Active = false,
|
||||
ActiveRounds = lastValue.ActiveRounds,
|
||||
DataType = lastValue.DataType,
|
||||
Source = lastValue.Source,
|
||||
UpdateTime = utcNow
|
||||
});
|
||||
}
|
||||
|
|
@ -246,7 +261,7 @@ public class ConversationStateService : IConversationStateService, IDisposable
|
|||
{
|
||||
if (!string.IsNullOrEmpty(property.Value.ToString()))
|
||||
{
|
||||
SetState(property.Name, property.Value);
|
||||
SetState(property.Name, property.Value, source: StateSource.Application);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using BotSharp.Abstraction.Conversations.Enums;
|
||||
using BotSharp.Abstraction.MLTasks;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
|
|
@ -47,14 +48,14 @@ public class TokenStatistics : ITokenStatistics
|
|||
// Accumulated Token
|
||||
var stat = _services.GetRequiredService<IConversationStateService>();
|
||||
var inputCount = int.Parse(stat.GetState("prompt_total", "0"));
|
||||
stat.SetState("prompt_total", stats.PromptCount + inputCount, false);
|
||||
stat.SetState("prompt_total", stats.PromptCount + inputCount, isNeedVersion: false, source: StateSource.Application);
|
||||
var outputCount = int.Parse(stat.GetState("completion_total", "0"));
|
||||
stat.SetState("completion_total", stats.CompletionCount + outputCount, false);
|
||||
stat.SetState("completion_total", stats.CompletionCount + outputCount, isNeedVersion: false, source: StateSource.Application);
|
||||
|
||||
// Total cost
|
||||
var total_cost = float.Parse(stat.GetState("llm_total_cost", "0"));
|
||||
total_cost += Cost;
|
||||
stat.SetState("llm_total_cost", total_cost, false);
|
||||
stat.SetState("llm_total_cost", total_cost, isNeedVersion: false, source: StateSource.Application);
|
||||
}
|
||||
|
||||
public void PrintStatistics()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using BotSharp.Abstraction.Routing;
|
||||
using BotSharp.Abstraction.Users.Models;
|
||||
|
||||
namespace BotSharp.OpenAPI.Controllers;
|
||||
|
||||
|
|
@ -166,11 +165,11 @@ public class ConversationController : ControllerBase
|
|||
routing.Context.SetMessageId(conversationId, inputMsg.MessageId);
|
||||
|
||||
conv.SetConversationId(conversationId, input.States);
|
||||
conv.States.SetState("channel", input.Channel)
|
||||
.SetState("provider", input.Provider)
|
||||
.SetState("model", input.Model)
|
||||
.SetState("temperature", input.Temperature)
|
||||
.SetState("sampling_factor", input.SamplingFactor);
|
||||
conv.States.SetState("channel", input.Channel, source: StateSource.External)
|
||||
.SetState("provider", input.Provider, source: StateSource.External)
|
||||
.SetState("model", input.Model, source: StateSource.External)
|
||||
.SetState("temperature", input.Temperature, source: StateSource.External)
|
||||
.SetState("sampling_factor", input.SamplingFactor, source: StateSource.External);
|
||||
|
||||
var response = new ChatResponseModel();
|
||||
|
||||
|
|
|
|||
|
|
@ -436,6 +436,9 @@ public class StreamingLogHook : ConversationHookBase, IContentGeneratingHook, IR
|
|||
BeforeActiveRounds = stateChange.BeforeActiveRounds,
|
||||
AfterValue = stateChange.AfterValue,
|
||||
AfterActiveRounds = stateChange.AfterActiveRounds,
|
||||
DataType = stateChange.DataType,
|
||||
Source = stateChange.Source,
|
||||
Readonly = stateChange.Readonly,
|
||||
CreateTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ public class StateMongoElement
|
|||
{
|
||||
public string Key { get; set; }
|
||||
public bool Versioning { get; set; }
|
||||
public bool Readonly { get; set; }
|
||||
public List<StateValueMongoElement> Values { get; set; }
|
||||
|
||||
public static StateMongoElement ToMongoElement(StateKeyValue state)
|
||||
|
|
@ -14,6 +15,7 @@ public class StateMongoElement
|
|||
{
|
||||
Key = state.Key,
|
||||
Versioning = state.Versioning,
|
||||
Readonly = state.Readonly,
|
||||
Values = state.Values?.Select(x => StateValueMongoElement.ToMongoElement(x))?.ToList() ?? new List<StateValueMongoElement>()
|
||||
};
|
||||
}
|
||||
|
|
@ -24,6 +26,7 @@ public class StateMongoElement
|
|||
{
|
||||
Key = state.Key,
|
||||
Versioning = state.Versioning,
|
||||
Readonly = state.Readonly,
|
||||
Values = state.Values?.Select(x => StateValueMongoElement.ToDomainElement(x))?.ToList() ?? new List<StateValue>()
|
||||
};
|
||||
}
|
||||
|
|
@ -35,6 +38,9 @@ public class StateValueMongoElement
|
|||
public string? MessageId { get; set; }
|
||||
public bool Active { get; set; }
|
||||
public int ActiveRounds { get; set; }
|
||||
public string DataType { get; set; }
|
||||
public string Source { get; set; }
|
||||
|
||||
public DateTime UpdateTime { get; set; }
|
||||
|
||||
public static StateValueMongoElement ToMongoElement(StateValue element)
|
||||
|
|
@ -45,6 +51,8 @@ public class StateValueMongoElement
|
|||
MessageId = element.MessageId,
|
||||
Active = element.Active,
|
||||
ActiveRounds = element.ActiveRounds,
|
||||
DataType = element.DataType,
|
||||
Source = element.Source,
|
||||
UpdateTime = element.UpdateTime
|
||||
};
|
||||
}
|
||||
|
|
@ -57,6 +65,8 @@ public class StateValueMongoElement
|
|||
MessageId = element.MessageId,
|
||||
Active = element.Active,
|
||||
ActiveRounds = element.ActiveRounds,
|
||||
DataType= element.DataType,
|
||||
Source = element.Source,
|
||||
UpdateTime = element.UpdateTime
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue