Исправление маппинга

This commit is contained in:
Alex Shibalkin 2025-02-27 14:01:31 +05:00
parent d2c4db015b
commit 2dca1cc722
9 changed files with 97 additions and 54 deletions

View File

@ -0,0 +1,6 @@
namespace DD.Persistence.Client.Clients.Mapping.Abstractions;
internal interface IMapperStorage
{
TimestampedSetMapper GetMapper<T>(Guid idDiscriminator);
TimestampedSetMapper? GetMapper(Guid idDiscriminator);
}

View File

@ -2,13 +2,23 @@
using DD.Persistence.Client.Clients.Mapping.Abstractions;
using DD.Persistence.Models;
using DD.Persistence.Models.Common;
using DD.Persistence.Models.Configurations;
using System.Text.Json;
namespace DD.Persistence.Client.Clients.Mapping.Clients;
/// <inheritdoc/>
public class SetpointMappingClient(ISetpointClient setpointClient, Dictionary<Guid, Type> mappingConfigs) : ISetpointMappingClient
public class SetpointMappingClient : ISetpointMappingClient
{
private readonly ISetpointClient setpointClient;
private readonly MappingConfig mappingConfigs;
public SetpointMappingClient(ISetpointClient setpointClient, MappingConfig mappingConfigs)
{
this.setpointClient = setpointClient;
this.mappingConfigs = mappingConfigs;
}
/// <inheritdoc/>
public async Task<IEnumerable<SetpointValueDto>> GetCurrent(IEnumerable<Guid> setpointKeys, CancellationToken token)
=> (await setpointClient.GetCurrent(setpointKeys, token))

View File

@ -2,21 +2,27 @@
using DD.Persistence.Client.Clients.Mapping.Abstractions;
using DD.Persistence.Models;
using DD.Persistence.Models.Common;
using System.Collections.Concurrent;
namespace DD.Persistence.Client.Clients.Mapping.Clients;
/// <inheritdoc/>
public class TimestampedMappingClient(ITimestampedValuesClient client, Dictionary<Guid, Type>? mappingConfigs) : ITimestampedMappingClient
internal class TimestampedMappingClient : ITimestampedMappingClient
{
private readonly ConcurrentDictionary<Guid, TimestampedSetMapper> mapperCache = new();
private readonly ITimestampedValuesClient client;
private readonly IMapperStorage mapperStorage;
public TimestampedMappingClient(ITimestampedValuesClient client, IMapperStorage mapperStorage)
{
this.client = client;
this.mapperStorage = mapperStorage;
}
/// <inheritdoc/>
public async Task<IEnumerable<T>> GetMapped<T>(Guid discriminatorId, DateTimeOffset? geTimestamp,
string? filterTree, IEnumerable<string>? columnNames, int skip, int take, CancellationToken token)
{
var data = await Get([discriminatorId], geTimestamp, filterTree, columnNames, skip, take, token);
var mapper = GetMapper<T>(discriminatorId);
var mapper = mapperStorage.GetMapper<T>(discriminatorId);
var mappedDtos = data.Select(mapper.DeserializeTimeStampedData).OfType<T>();
@ -27,7 +33,7 @@ public class TimestampedMappingClient(ITimestampedValuesClient client, Dictionar
public async Task<IEnumerable<T>> GetLastMapped<T>(Guid idDiscriminator, int take, CancellationToken token)
{
var data = await GetLast(idDiscriminator, take, token);
var mapper = GetMapper<T>(idDiscriminator);
var mapper = mapperStorage.GetMapper<T>(idDiscriminator);
var mappedDtos = data.Select(mapper.DeserializeTimeStampedData).OfType<T>();
@ -43,13 +49,9 @@ public class TimestampedMappingClient(ITimestampedValuesClient client, Dictionar
var result = discriminatorIds
.ToDictionary(discriminatorId => discriminatorId, discriminatorId =>
{
if (mappingConfigs is null)
throw new ArgumentNullException(nameof(mappingConfigs));
var mapper = mapperStorage.GetMapper(discriminatorId);
if (!mappingConfigs.TryGetValue(discriminatorId, out var type))
throw new InvalidCastException();
var mapper = GetMapper(discriminatorId, type);
ArgumentNullException.ThrowIfNull(mapper);
var mappedDtos = data
.Where(e => e.DiscriminatorId == discriminatorId)
@ -58,19 +60,6 @@ public class TimestampedMappingClient(ITimestampedValuesClient client, Dictionar
return mappedDtos;
});
//var genericMapperType = typeof(TimestampedSetMapper<>).MakeGenericType(type);
//var ttype = typeof(TimestampedSetMapper<object>);
//object b = 0;
//var mapper = MapperMethodInfo
// .MakeGenericMethod([type])
// .Invoke(this, [discriminatorId]);
//var deserializeMethod = genericMapperType
// .GetMethod(nameof(TimestampedSetMapper<object>.DeserializeTimeStampedData))!;
// ToDo: приводим к Dictionary
return result;
}
@ -113,13 +102,5 @@ public class TimestampedMappingClient(ITimestampedValuesClient client, Dictionar
client.Dispose();
}
private TimestampedSetMapper GetMapper(Guid idDiscriminator, Type type)
{
return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, type));
}
private TimestampedSetMapper GetMapper<T>(Guid idDiscriminator)
{
return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, typeof(T)));
}
}

View File

@ -0,0 +1,29 @@
using DD.Persistence.Client.Clients.Mapping.Abstractions;
using DD.Persistence.Models.Configurations;
using System;
using System.Collections.Concurrent;
namespace DD.Persistence.Client.Clients.Mapping;
internal class MapperStorage : IMapperStorage
{
private readonly ConcurrentDictionary<Guid, TimestampedSetMapper> mapperCache = new();
private readonly MappingConfig mappingConfigs;
public MapperStorage(MappingConfig mappingConfigs)
{
this.mappingConfigs = mappingConfigs;
}
public TimestampedSetMapper? GetMapper(Guid idDiscriminator)
{
if(mappingConfigs.TryGetValue(idDiscriminator, out var type))
return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, type));
return null;
}
public TimestampedSetMapper GetMapper<T>(Guid idDiscriminator)
{
return mapperCache.GetOrAdd(idDiscriminator, name => new TimestampedSetMapper(idDiscriminator, typeof(T)));
}
}

View File

@ -1,8 +1,10 @@
using DD.Persistence.Client.Clients;
using DD.Persistence.Client.Clients.Interfaces;
using DD.Persistence.Client.Clients.Mapping;
using DD.Persistence.Client.Clients.Mapping.Abstractions;
using DD.Persistence.Client.Clients.Mapping.Clients;
using DD.Persistence.Models;
using DD.Persistence.Models.Configurations;
using Microsoft.Extensions.DependencyInjection;
namespace DD.Persistence.Client;
@ -17,7 +19,7 @@ public static class DependencyInjection
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddPersistenceClients(this IServiceCollection services, Dictionary<Guid, Type>? setpointTypeConfigs = null)
public static IServiceCollection AddPersistenceClients(this IServiceCollection services)
{
services.AddTransient(typeof(IRefitClientFactory<>), typeof(RefitClientFactory<>));
services.AddTransient<IChangeLogClient, ChangeLogClient>();
@ -31,18 +33,13 @@ public static class DependencyInjection
}
public static IServiceCollection AddPersistenceMapping(this IServiceCollection services, Dictionary<Guid, Type>? mappingConfigs)
public static IServiceCollection AddPersistenceMapping(this IServiceCollection services, MappingConfig mappingConfigs)
{
services.AddTransient<ISetpointMappingClient, SetpointMappingClient>(provider =>
{
var client = provider.GetRequiredService<ISetpointClient>();
return new SetpointMappingClient(client, mappingConfigs);
});
services.AddTransient<ITimestampedMappingClient, TimestampedMappingClient>(provider =>
{
var client = provider.GetRequiredService<ITimestampedValuesClient>();
return new TimestampedMappingClient(client, mappingConfigs);
});
services.AddSingleton(mappingConfigs);
services.AddSingleton<IMapperStorage, MapperStorage>();
services.AddTransient<ISetpointMappingClient, SetpointMappingClient>();
services.AddTransient<ITimestampedMappingClient, TimestampedMappingClient>();
return services;
}
}

View File

@ -3,6 +3,7 @@ using DD.Persistence.Client.Clients.Interfaces;
using DD.Persistence.Client.Clients.Interfaces.Refit;
using DD.Persistence.Client.Clients.Mapping.Clients;
using DD.Persistence.Database.Entity;
using DD.Persistence.Models.Configurations;
using Microsoft.Extensions.DependencyInjection;
using System.Text.Json;
using Xunit;
@ -28,7 +29,7 @@ namespace DD.Persistence.IntegrationTests.Controllers
{
var id = Guid.Parse("e0fcad22-1761-476e-a729-a3c59d51ba41");
var config = new Dictionary<Guid, Type>();
var config = new MappingConfig();
config[id] = typeof(float);
var setpointMapper = new SetpointMappingClient(setpointClient, config);

View File

@ -0,0 +1,4 @@
namespace DD.Persistence.Models.Configurations;
public class MappingConfig : Dictionary<Guid, Type>
{
}

View File

@ -1,6 +1,8 @@
using DD.Persistence.Client.Clients.Interfaces;
using DD.Persistence.Client.Clients.Mapping;
using DD.Persistence.Client.Clients.Mapping.Clients;
using DD.Persistence.Models;
using DD.Persistence.Models.Configurations;
using NSubstitute;
using System.Text.Json;
@ -15,17 +17,19 @@ public class MappingClientsTest
private readonly ITimestampedValuesClient timestampedValuesClient = Substitute.For<ITimestampedValuesClient>();
private readonly TimestampedMappingClient timestampedMappingClient;
private readonly Dictionary<Guid, Type> mappingConfigs = new Dictionary<Guid, Type>()
{
{ Guid.NewGuid(), typeof(FirstTestDto) },
{ Guid.NewGuid(), typeof(SecondTestDto) }
};
private readonly MappingConfig mappingConfigs;
public MappingClientsTest()
{
timestampedMappingClient = new TimestampedMappingClient(timestampedValuesClient, mappingConfigs);
mappingConfigs = GetConfig();
var storage = new MapperStorage(mappingConfigs);
timestampedMappingClient = new TimestampedMappingClient(timestampedValuesClient, storage);
}
[Fact]
public async Task GetMultiMapped()
{
@ -82,4 +86,12 @@ public class MappingClientsTest
expectedId = getResult[1].Values[nameof(SecondTestDto.Id)].ToString();
Assert.Equal(expectedId, actualId);
}
private MappingConfig GetConfig()
{
var config = new MappingConfig();
config[Guid.NewGuid()] = typeof(FirstTestDto);
config[Guid.NewGuid()] = typeof(SecondTestDto);
return config;
}
}

View File

@ -8,6 +8,9 @@
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>DD.Persistence.IntegrationTests</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>DD.Persistence.Test</_Parameter1>
</AssemblyAttribute>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>DynamicProxyGenAssembly2</_Parameter1>
</AssemblyAttribute>