2025-01-20 15:12:40 +05:00
|
|
|
|
using DD.Persistence.Models;
|
|
|
|
|
using System.Collections.Concurrent;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
using System.Text.Json;
|
|
|
|
|
|
2025-02-14 13:26:47 +05:00
|
|
|
|
namespace DD.Persistence.Client.Clients.Mapping;
|
2025-01-20 15:12:40 +05:00
|
|
|
|
|
2025-02-24 15:21:02 +05:00
|
|
|
|
internal class TimestampedSetMapper
|
2025-01-20 15:12:40 +05:00
|
|
|
|
{
|
2025-02-24 15:21:02 +05:00
|
|
|
|
private readonly Type entityType;
|
2025-01-20 15:12:40 +05:00
|
|
|
|
public Guid IdDiscriminator { get; }
|
|
|
|
|
private readonly ConcurrentDictionary<string, PropertyInfo?> PropertyCache = new();
|
|
|
|
|
|
2025-02-24 15:21:02 +05:00
|
|
|
|
public TimestampedSetMapper(Guid idDiscriminator, Type entityType)
|
2025-01-20 15:12:40 +05:00
|
|
|
|
{
|
|
|
|
|
IdDiscriminator = idDiscriminator;
|
2025-02-24 15:21:02 +05:00
|
|
|
|
this.entityType = entityType;
|
2025-01-20 15:12:40 +05:00
|
|
|
|
}
|
|
|
|
|
|
2025-02-24 15:21:02 +05:00
|
|
|
|
public object DeserializeTimeStampedData(TimestampedValuesDto data)
|
2025-01-20 15:12:40 +05:00
|
|
|
|
{
|
|
|
|
|
if (entityType.IsValueType)
|
|
|
|
|
return MapStruct(data);
|
2025-02-24 15:21:02 +05:00
|
|
|
|
|
|
|
|
|
return MapClass(data);
|
2025-01-20 15:12:40 +05:00
|
|
|
|
}
|
|
|
|
|
|
2025-02-24 15:21:02 +05:00
|
|
|
|
private object MapClass(TimestampedValuesDto data)
|
2025-01-20 15:12:40 +05:00
|
|
|
|
{
|
2025-02-24 15:21:02 +05:00
|
|
|
|
var entity = RuntimeHelpers.GetUninitializedObject(entityType);
|
2025-01-21 10:53:16 +05:00
|
|
|
|
foreach (var (propertyName, value) in data.Values)
|
2025-01-20 15:12:40 +05:00
|
|
|
|
{
|
|
|
|
|
if (value is JsonElement jsonElement)
|
|
|
|
|
SetPropertyValueFromJson(ref entity, propertyName, jsonElement);
|
|
|
|
|
}
|
2025-02-24 15:21:02 +05:00
|
|
|
|
SetPropertyValue(ref entity, nameof(TimestampedValuesDto.Timestamp), data.Timestamp);
|
|
|
|
|
SetPropertyValue(ref entity, nameof(TimestampedValuesDto.DiscriminatorId), data.DiscriminatorId);
|
|
|
|
|
|
2025-01-20 15:12:40 +05:00
|
|
|
|
return entity;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-24 15:21:02 +05:00
|
|
|
|
private object MapStruct(TimestampedValuesDto data)
|
2025-01-20 15:12:40 +05:00
|
|
|
|
{
|
2025-02-24 15:21:02 +05:00
|
|
|
|
var entity = Activator.CreateInstance(entityType);
|
2025-01-20 15:12:40 +05:00
|
|
|
|
object boxedEntity = entity!;
|
2025-01-21 10:53:16 +05:00
|
|
|
|
foreach (var (propertyName, value) in data.Values)
|
2025-01-20 15:12:40 +05:00
|
|
|
|
{
|
|
|
|
|
if (value is JsonElement jsonElement)
|
|
|
|
|
SetPropertyValueForStructFromJson(ref boxedEntity, propertyName, jsonElement);
|
|
|
|
|
}
|
2025-02-24 15:21:02 +05:00
|
|
|
|
SetPropertyValueForStruct(ref boxedEntity, nameof(TimestampedValuesDto.Timestamp), data.Timestamp);
|
|
|
|
|
SetPropertyValueForStruct(ref boxedEntity, nameof(TimestampedValuesDto.DiscriminatorId), data.DiscriminatorId);
|
2025-01-20 15:12:40 +05:00
|
|
|
|
|
2025-02-24 15:21:02 +05:00
|
|
|
|
return boxedEntity;
|
2025-01-20 15:12:40 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void SetPropertyValueForStructFromJson(ref object entity, string propertyName, JsonElement element)
|
|
|
|
|
{
|
|
|
|
|
var property = GetPropertyInfo(propertyName);
|
|
|
|
|
if (property is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var value = element.Deserialize(property.PropertyType);
|
|
|
|
|
property.SetValue(entity, value);
|
|
|
|
|
}
|
2025-02-24 15:21:02 +05:00
|
|
|
|
catch (Exception) { }
|
2025-01-20 15:12:40 +05:00
|
|
|
|
}
|
|
|
|
|
private void SetPropertyValueForStruct(ref object entity, string propertyName, object value)
|
|
|
|
|
{
|
|
|
|
|
var property = GetPropertyInfo(propertyName);
|
|
|
|
|
if (property is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var convertedValue = Convert.ChangeType(value, property.PropertyType);
|
|
|
|
|
property.SetValue(entity, convertedValue);
|
|
|
|
|
}
|
2025-02-24 15:21:02 +05:00
|
|
|
|
catch (Exception) { }
|
2025-01-20 15:12:40 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-02-24 15:21:02 +05:00
|
|
|
|
private void SetPropertyValueFromJson(ref object entity, string propertyName, JsonElement jsonElement)
|
2025-01-20 15:12:40 +05:00
|
|
|
|
{
|
|
|
|
|
var property = GetPropertyInfo(propertyName);
|
|
|
|
|
|
|
|
|
|
if (property is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var value = jsonElement.Deserialize(property.PropertyType);
|
|
|
|
|
property.SetValue(entity, value);
|
|
|
|
|
}
|
2025-02-24 15:21:02 +05:00
|
|
|
|
catch (Exception) { }
|
2025-01-20 15:12:40 +05:00
|
|
|
|
}
|
|
|
|
|
|
2025-02-24 15:21:02 +05:00
|
|
|
|
private void SetPropertyValue(ref object entity, string propertyName, object value)
|
2025-01-20 15:12:40 +05:00
|
|
|
|
{
|
|
|
|
|
var property = GetPropertyInfo(propertyName);
|
|
|
|
|
if (property is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var convertedValue = Convert.ChangeType(value, property.PropertyType);
|
|
|
|
|
property.SetValue(entity, convertedValue);
|
|
|
|
|
}
|
2025-02-24 15:21:02 +05:00
|
|
|
|
catch (Exception) { }
|
2025-01-20 15:12:40 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private PropertyInfo? GetPropertyInfo(string propertyName)
|
|
|
|
|
{
|
|
|
|
|
return PropertyCache.GetOrAdd(propertyName, name => entityType.GetProperty(name));
|
|
|
|
|
}
|
|
|
|
|
}
|