Skip to content

Commit d0a7388

Browse files
committed
IRqlMapAccessor moved to abstractions
1 parent 830251e commit d0a7388

File tree

10 files changed

+84
-45
lines changed

10 files changed

+84
-45
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace SoftwareOne.Rql.Abstractions.Mapping;
2+
3+
public interface IRqlMapAccessor
4+
{
5+
Dictionary<string, IRqlMapEntry> GetMap<TFrom, TTo>()
6+
=> GetMap(typeof(TFrom), typeof(TTo));
7+
8+
Dictionary<string, IRqlMapEntry> GetMap(Type typeFrom, Type typeTo);
9+
10+
public IEnumerable<IRqlMapEntry> GetEntries<TFrom, TTo>()
11+
=> GetEntries(typeof(TFrom), typeof(TTo));
12+
13+
public IEnumerable<IRqlMapEntry> GetEntries(Type typeFrom, Type typeTo);
14+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System.Linq.Expressions;
2+
3+
namespace SoftwareOne.Rql.Abstractions.Mapping;
4+
5+
public interface IRqlMapEntry
6+
{
7+
IRqlPropertyInfo TargetProperty { get; }
8+
9+
LambdaExpression SourceExpression { get; }
10+
11+
IReadOnlyDictionary<string, IRqlMapEntry>? InlineMap { get; }
12+
13+
IReadOnlyCollection<IRqlMapEntryCondition>? Conditions { get; }
14+
15+
bool IsDynamic { get; }
16+
17+
Type TargetType => TargetProperty.ElementType ?? TargetProperty.Property.PropertyType;
18+
}
19+
20+
public interface IRqlMapEntryCondition
21+
{
22+
LambdaExpression If { get; }
23+
24+
IRqlMapEntry Entry { get; }
25+
}

src/SoftwareOne.Rql.Linq/RqlExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using SoftwareOne.Rql.Abstractions.Collection;
55
using SoftwareOne.Rql.Abstractions.Configuration;
66
using SoftwareOne.Rql.Abstractions.Group;
7+
using SoftwareOne.Rql.Abstractions.Mapping;
78
using SoftwareOne.Rql.Abstractions.Unary;
89
using SoftwareOne.Rql.Client;
910
using SoftwareOne.Rql.Linq;

src/SoftwareOne.Rql.Linq/Services/Mapping/EntityMapCache.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
using System.Collections.Concurrent;
1+
using SoftwareOne.Rql.Abstractions.Mapping;
2+
using System.Collections.Concurrent;
23

34
namespace SoftwareOne.Rql.Linq.Services.Mapping;
45

56
internal interface IEntityMapCache
67
{
7-
Dictionary<string, RqlMapEntry> Get(Type typeFrom, Type typeTo);
8+
Dictionary<string, IRqlMapEntry> Get(Type typeFrom, Type typeTo);
89
}
910

1011
internal class EntityMapCache(IServiceProvider serviceProvider) : IEntityMapCache
1112
{
12-
private readonly ConcurrentDictionary<(Type, Type), Dictionary<string, RqlMapEntry>> _cache = [];
13+
private readonly ConcurrentDictionary<(Type, Type), Dictionary<string, IRqlMapEntry>> _cache = [];
1314

1415
private readonly IServiceProvider _serviceProvider = serviceProvider;
1516

16-
public Dictionary<string, RqlMapEntry> Get(Type typeFrom, Type typeTo)
17+
public Dictionary<string, IRqlMapEntry> Get(Type typeFrom, Type typeTo)
1718
{
1819
var key = (typeFrom, typeTo);
1920
return _cache.GetOrAdd(key, k =>
Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,13 @@
1-
using SoftwareOne.Rql.Linq.Services.Mapping;
1+
using SoftwareOne.Rql.Abstractions.Mapping;
2+
using SoftwareOne.Rql.Linq.Services.Mapping;
23

3-
#pragma warning disable IDE0130
44
namespace SoftwareOne.Rql;
55

6-
public interface IRqlMapAccessor
7-
{
8-
Dictionary<string, RqlMapEntry> GetMap<TFrom, TTo>()
9-
=> GetMap(typeof(TFrom), typeof(TTo));
10-
11-
Dictionary<string, RqlMapEntry> GetMap(Type typeFrom, Type typeTo);
12-
13-
public IEnumerable<RqlMapEntry> GetEntries<TFrom, TTo>()
14-
=> GetEntries(typeof(TFrom), typeof(TTo));
15-
16-
public IEnumerable<RqlMapEntry> GetEntries(Type typeFrom, Type typeTo);
17-
}
18-
196
internal class RqlMapAccessor(IEntityMapCache mapCache) : IRqlMapAccessor
207
{
21-
public IEnumerable<RqlMapEntry> GetEntries(Type typeFrom, Type typeTo)
8+
public IEnumerable<IRqlMapEntry> GetEntries(Type typeFrom, Type typeTo)
229
=> GetMap(typeFrom, typeTo).Values;
2310

24-
public Dictionary<string, RqlMapEntry> GetMap(Type typeFrom, Type typeTo)
11+
public Dictionary<string, IRqlMapEntry> GetMap(Type typeFrom, Type typeTo)
2512
=> mapCache.Get(typeFrom, typeTo);
2613
}

src/SoftwareOne.Rql.Linq/Services/Mapping/MappingService.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using SoftwareOne.Rql.Abstractions;
1+
using SoftwareOne.Rql.Abstractions.Mapping;
22
using SoftwareOne.Rql.Linq.Core.Metadata;
33
using SoftwareOne.Rql.Linq.Services.Context;
44
using System.Collections;
@@ -32,7 +32,7 @@ private MemberInitExpression MakeInitExpression(Expression param, IRqlNode rqlNo
3232
return MakeInitExpression(param, rqlNode, typeTo, typeMap);
3333
}
3434

35-
private MemberInitExpression MakeInitExpression(Expression param, IRqlNode rqlNode, Type typeTo, IReadOnlyDictionary<string, RqlMapEntry> typeMap)
35+
private MemberInitExpression MakeInitExpression(Expression param, IRqlNode rqlNode, Type typeTo, IReadOnlyDictionary<string, IRqlMapEntry> typeMap)
3636
{
3737
var bindings = new List<MemberBinding>(_queryContext.Graph.Count);
3838

@@ -49,7 +49,7 @@ private MemberInitExpression MakeInitExpression(Expression param, IRqlNode rqlNo
4949
return Expression.MemberInit(Expression.New(typeTo.GetConstructor(Type.EmptyTypes)!), bindings);
5050
}
5151

52-
private Expression TryMakeConditionalBindExpression(Expression param, IRqlNode rqlNode, Expression defaultExpression, RqlMapEntry parentEntry)
52+
private Expression TryMakeConditionalBindExpression(Expression param, IRqlNode rqlNode, Expression defaultExpression, IRqlMapEntry parentEntry)
5353
{
5454
if (parentEntry.Conditions == null || parentEntry.Conditions.Count == 0)
5555
return defaultExpression;
@@ -58,7 +58,7 @@ private Expression TryMakeConditionalBindExpression(Expression param, IRqlNode r
5858

5959
for (int i = parentEntry.Conditions.Count - 1; i >= 0; i--)
6060
{
61-
var condition = parentEntry.Conditions[i];
61+
var condition = parentEntry.Conditions.ElementAt(i);
6262

6363
var replaceParamVisitor = new ReplaceParameterVisitor(condition.If.Parameters[0], param);
6464
var ifExpression = replaceParamVisitor.Visit(condition.If.Body);
@@ -69,7 +69,7 @@ private Expression TryMakeConditionalBindExpression(Expression param, IRqlNode r
6969
return conditionalExpr;
7070
}
7171

72-
private Expression MakeBindExpression(Expression param, IRqlNode node, RqlMapEntry map)
72+
private Expression MakeBindExpression(Expression param, IRqlNode node, IRqlMapEntry map)
7373
{
7474
var targetType = node.Property.Property.PropertyType;
7575
var replaceParamVisitor = new ReplaceParameterVisitor(map.SourceExpression.Parameters[0], param);
@@ -94,7 +94,7 @@ private Expression MakeBindExpression(Expression param, IRqlNode node, RqlMapEnt
9494
return fromExpression;
9595
}
9696

97-
private Expression MakeReferenceInit(Expression fromExpression, IRqlNode node, RqlMapEntry map)
97+
private Expression MakeReferenceInit(Expression fromExpression, IRqlNode node, IRqlMapEntry map)
9898
{
9999
var innerMap = GetInnerMapFromEntry(fromExpression.Type, map);
100100

@@ -113,7 +113,7 @@ private Expression MakeReferenceInit(Expression fromExpression, IRqlNode node, R
113113
return fromExpression;
114114
}
115115

116-
private Expression MakeCollectionInit(Expression fromExpression, IRqlNode node, RqlMapEntry map)
116+
private Expression MakeCollectionInit(Expression fromExpression, IRqlNode node, IRqlMapEntry map)
117117
{
118118
// Temporarily only support List
119119
if (!typeof(IList).IsAssignableFrom(node.Property.Property.PropertyType))
@@ -133,6 +133,6 @@ private Expression MakeCollectionInit(Expression fromExpression, IRqlNode node,
133133
return Expression.Call(null, functions.GetToList(), selectCall);
134134
}
135135

136-
private IReadOnlyDictionary<string, RqlMapEntry> GetInnerMapFromEntry(Type typeFrom, RqlMapEntry map)
136+
private IReadOnlyDictionary<string, IRqlMapEntry> GetInnerMapFromEntry(Type typeFrom, IRqlMapEntry map)
137137
=> map.InlineMap ?? _mapCache.Get(typeFrom, map.TargetType);
138138
}
Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,36 @@
11
using SoftwareOne.Rql.Abstractions;
2+
using SoftwareOne.Rql.Abstractions.Mapping;
23
using System.Linq.Expressions;
34

4-
#pragma warning disable IDE0130
5-
namespace SoftwareOne.Rql;
65

7-
public class RqlMapEntry
6+
namespace SoftwareOne.Rql.Linq.Services.Mapping;
7+
8+
internal class RqlMapEntry : IRqlMapEntry
89
{
910
public IRqlPropertyInfo TargetProperty { get; internal set; } = null!;
1011

1112
public LambdaExpression SourceExpression { get; internal set; } = null!;
1213

13-
public IReadOnlyDictionary<string, RqlMapEntry>? InlineMap { get; internal set; }
14+
public IReadOnlyDictionary<string, IRqlMapEntry>? InlineMap { get; internal set; }
1415

15-
public List<RqlMapEntryCondition>? Conditions { get; internal set; }
16+
public IReadOnlyCollection<IRqlMapEntryCondition>? Conditions { get; internal set; }
1617

17-
public bool IsDynamic { get; internal set; }
18+
public void AddCondition(IRqlMapEntryCondition condition)
19+
{
20+
if (Conditions is null)
21+
Conditions = [condition];
22+
else if (Conditions is List<IRqlMapEntryCondition> list)
23+
list.Add(condition);
24+
else
25+
Conditions = [.. Conditions, condition];
26+
}
1827

19-
public Type TargetType => TargetProperty.ElementType ?? TargetProperty.Property.PropertyType;
28+
public bool IsDynamic { get; internal set; }
2029
}
2130

22-
public class RqlMapEntryCondition
31+
internal class RqlMapEntryCondition : IRqlMapEntryCondition
2332
{
2433
public LambdaExpression If { get; init; } = null!;
2534

26-
public RqlMapEntry Entry { get; init; } = null!;
35+
public IRqlMapEntry Entry { get; init; } = null!;
2736
}

src/SoftwareOne.Rql.Linq/Services/Mapping/RqlMapperContext.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
using SoftwareOne.Rql.Abstractions;
2+
using SoftwareOne.Rql.Abstractions.Mapping;
23
using System.Linq.Expressions;
34

45
namespace SoftwareOne.Rql.Linq.Services.Mapping;
56

67
internal abstract class RqlMapperContext
78
{
8-
public abstract Dictionary<string, RqlMapEntry> Mapping { get; }
9+
public abstract Dictionary<string, IRqlMapEntry> Mapping { get; }
910

1011
public abstract void AddMissing();
1112
}
@@ -14,9 +15,9 @@ internal class RqlMapperContext<TStorage, TView> : RqlMapperContext, IRqlMapperC
1415
{
1516
private readonly IRqlMetadataProvider _rqlMetadataProvider;
1617
private readonly Dictionary<string, IRqlPropertyInfo> _targetProperties;
17-
private readonly Dictionary<string, RqlMapEntry> _mapping;
18+
private readonly Dictionary<string, IRqlMapEntry> _mapping;
1819
private readonly HashSet<string> _ignored;
19-
private readonly HashSet<RqlMapEntry> _switch;
20+
private readonly HashSet<IRqlMapEntry> _switch;
2021

2122
public RqlMapperContext(IRqlMetadataProvider rqlMetadataProvider)
2223
{
@@ -63,7 +64,7 @@ public IRqlMapperContext<TStorage, TView> Ignore<TTo>(Expression<Func<TView, TTo
6364
return this;
6465
}
6566

66-
public override Dictionary<string, RqlMapEntry> Mapping => _mapping;
67+
public override Dictionary<string, IRqlMapEntry> Mapping => _mapping;
6768

6869
public override void AddMissing()
6970
{
@@ -108,7 +109,7 @@ public override void AddMissing()
108109

109110
private RqlMapperContext<TStorage, TView> MapInternal<TFrom, TTo>(IRqlPropertyInfo target, LambdaExpression source, bool isDynamic, Action<IRqlMapperContext<TFrom, TTo>>? configureInline)
110111
{
111-
Dictionary<string, RqlMapEntry>? inline = null;
112+
Dictionary<string, IRqlMapEntry>? inline = null;
112113
if (configureInline != null)
113114
{
114115
var mapperContext = new RqlMapperContext<TFrom, TTo>(_rqlMetadataProvider);
@@ -127,7 +128,7 @@ private RqlMapperContext<TStorage, TView> MapInternal<TFrom, TTo>(IRqlPropertyIn
127128
});
128129
}
129130

130-
private RqlMapperContext<TStorage, TView> MapInternal(RqlMapEntry mapEntry)
131+
private RqlMapperContext<TStorage, TView> MapInternal(IRqlMapEntry mapEntry)
131132
{
132133
_mapping.Add(mapEntry.TargetProperty.Property.Name, mapEntry);
133134
return this;

src/SoftwareOne.Rql.Linq/Services/Mapping/RqlMapperSwitchContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ internal class RqlMapperSwitchContext<TFromOwner>(RqlMapEntry parentEntry) : IRq
77
public IRqlMapperSwitchContextFinalizer<TFromOwner> Case<TFrom>(Expression<Func<TFromOwner, bool>> condition, Expression<Func<TFromOwner, TFrom?>> from, bool mapStatic = false)
88
{
99
parentEntry.Conditions ??= [];
10-
parentEntry.Conditions.Add(new RqlMapEntryCondition
10+
parentEntry.AddCondition(new RqlMapEntryCondition
1111
{
1212
If = condition,
1313
Entry = new RqlMapEntry

tests/SoftwareOne.Rql.Linq.UnitTests/Services/Mapping/RqlMapAssessorTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using FluentAssertions;
22
using Microsoft.Extensions.DependencyInjection;
3+
using SoftwareOne.Rql.Abstractions.Mapping;
34
using Xunit;
45

56
namespace SoftwareOne.Rql.Linq.UnitTests.Services.Mapping;

0 commit comments

Comments
 (0)