mirror of
				https://github.com/Biarity/Sieve.git
				synced 2025-10-31 00:39:12 +01:00 
			
		
		
		
	Allowed configuring properties with identical name
This commit is contained in:
		| @@ -4,20 +4,19 @@ using System.Collections.Generic; | |||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Linq.Expressions; | using System.Linq.Expressions; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
| using System.Text; |  | ||||||
|  |  | ||||||
| namespace Sieve.Services | namespace Sieve.Services | ||||||
| { | { | ||||||
| 	public class SievePropertyMapper | 	public class SievePropertyMapper | ||||||
|     { |     { | ||||||
|         private readonly Dictionary<Type, Dictionary<PropertyInfo, ISievePropertyMetadata>> _map |         private readonly Dictionary<Type, ICollection<KeyValuePair<PropertyInfo, ISievePropertyMetadata>>> _map | ||||||
|             = new Dictionary<Type, Dictionary<PropertyInfo, ISievePropertyMetadata>>(); |             = new Dictionary<Type, ICollection<KeyValuePair<PropertyInfo, ISievePropertyMetadata>>>(); | ||||||
|  |  | ||||||
|         public PropertyFluentApi<TEntity> Property<TEntity>(Expression<Func<TEntity, object>> expression) |         public PropertyFluentApi<TEntity> Property<TEntity>(Expression<Func<TEntity, object>> expression) | ||||||
|         { |         { | ||||||
|             if(!_map.ContainsKey(typeof(TEntity))) |             if(!_map.ContainsKey(typeof(TEntity))) | ||||||
|             { |             { | ||||||
|                 _map.Add(typeof(TEntity), new Dictionary<PropertyInfo, ISievePropertyMetadata>()); |                 _map.Add(typeof(TEntity), new List<KeyValuePair<PropertyInfo, ISievePropertyMetadata>>()); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return new PropertyFluentApi<TEntity>(this, expression); |             return new PropertyFluentApi<TEntity>(this, expression); | ||||||
| @@ -65,13 +64,16 @@ namespace Sieve.Services | |||||||
|  |  | ||||||
|             private void UpdateMap() |             private void UpdateMap() | ||||||
|             { |             { | ||||||
|                 _sievePropertyMapper._map[typeof(TEntity)][_property] = new SievePropertyMetadata() |                 var metadata = new SievePropertyMetadata() | ||||||
|                 { |                 { | ||||||
|                     Name = _name, |                     Name = _name, | ||||||
|                     FullName = _fullName, |                     FullName = _fullName, | ||||||
|                     CanFilter = _canFilter, |                     CanFilter = _canFilter, | ||||||
|                     CanSort = _canSort |                     CanSort = _canSort | ||||||
|                 }; |                 }; | ||||||
|  |                 var pair = new KeyValuePair<PropertyInfo, ISievePropertyMetadata>(_property, metadata); | ||||||
|  |  | ||||||
|  |                 _sievePropertyMapper._map[typeof(TEntity)].Add(pair); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             private static (string, PropertyInfo) GetPropertyInfo(Expression<Func<TEntity, object>> exp) |             private static (string, PropertyInfo) GetPropertyInfo(Expression<Func<TEntity, object>> exp) | ||||||
| @@ -105,8 +107,8 @@ namespace Sieve.Services | |||||||
|                 var result = _map[typeof(TEntity)] |                 var result = _map[typeof(TEntity)] | ||||||
|                     .FirstOrDefault(kv => |                     .FirstOrDefault(kv => | ||||||
|                     kv.Value.Name.Equals(name, isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase) |                     kv.Value.Name.Equals(name, isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase) | ||||||
|                     && (canSortRequired ? kv.Value.CanSort : true) |                     && (!canSortRequired || kv.Value.CanSort) | ||||||
|                     && (canFilterRequired ? kv.Value.CanFilter : true)); |                     && (!canFilterRequired || kv.Value.CanFilter)); | ||||||
|  |  | ||||||
|                 return (result.Value?.FullName, result.Key); |                 return (result.Value?.FullName, result.Key); | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| using System; | using System; | ||||||
| using Sieve.Attributes; | using Sieve.Attributes; | ||||||
|  | using SieveUnitTests.ValueObjects; | ||||||
|  |  | ||||||
| namespace SieveUnitTests.Entities | namespace SieveUnitTests.Entities | ||||||
| { | { | ||||||
| @@ -7,6 +8,10 @@ namespace SieveUnitTests.Entities | |||||||
|     { |     { | ||||||
|         public int Id { get; set; } |         public int Id { get; set; } | ||||||
|  |  | ||||||
|  |         public Name AuthorFirstName { get; set; } | ||||||
|  |  | ||||||
|  |         public Name AuthorLastName { get; set; } | ||||||
|  |  | ||||||
|         [Sieve(CanFilter = true, CanSort = true)] |         [Sieve(CanFilter = true, CanSort = true)] | ||||||
|         public DateTimeOffset DateCreated { get; set; } = DateTimeOffset.UtcNow; |         public DateTimeOffset DateCreated { get; set; } = DateTimeOffset.UtcNow; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ using Sieve.Models; | |||||||
| using Sieve.Services; | using Sieve.Services; | ||||||
| using SieveUnitTests.Entities; | using SieveUnitTests.Entities; | ||||||
| using SieveUnitTests.Services; | using SieveUnitTests.Services; | ||||||
|  | using SieveUnitTests.ValueObjects; | ||||||
|  |  | ||||||
| namespace SieveUnitTests | namespace SieveUnitTests | ||||||
| { | { | ||||||
| @@ -63,17 +64,23 @@ namespace SieveUnitTests | |||||||
|                 new Comment() { |                 new Comment() { | ||||||
|                     Id = 0, |                     Id = 0, | ||||||
|                     DateCreated = DateTimeOffset.UtcNow.AddDays(-20), |                     DateCreated = DateTimeOffset.UtcNow.AddDays(-20), | ||||||
|                     Text = "This is an old comment." |                     Text = "This is an old comment.", | ||||||
|  |                     AuthorFirstName = new Name("FirstName1"), | ||||||
|  |                     AuthorLastName = new Name("LastName1") | ||||||
|                 }, |                 }, | ||||||
|                 new Comment() { |                 new Comment() { | ||||||
|                     Id = 1, |                     Id = 1, | ||||||
|                     DateCreated = DateTimeOffset.UtcNow.AddDays(-1), |                     DateCreated = DateTimeOffset.UtcNow.AddDays(-1), | ||||||
|                     Text = "This is a fairly new comment." |                     Text = "This is a fairly new comment.", | ||||||
|  |                     AuthorFirstName = new Name("FirstName2"), | ||||||
|  |                     AuthorLastName = new Name("LastName2") | ||||||
|                 }, |                 }, | ||||||
|                 new Comment() { |                 new Comment() { | ||||||
|                     Id = 2, |                     Id = 2, | ||||||
|                     DateCreated = DateTimeOffset.UtcNow, |                     DateCreated = DateTimeOffset.UtcNow, | ||||||
|                     Text = "This is a brand new comment. ()" |                     Text = "This is a brand new comment. ()", | ||||||
|  |                     AuthorFirstName = new Name("FirstName3"), | ||||||
|  |                     AuthorLastName = new Name("LastName3") | ||||||
|                 }, |                 }, | ||||||
|             }.AsQueryable(); |             }.AsQueryable(); | ||||||
|         } |         } | ||||||
| @@ -365,5 +372,20 @@ namespace SieveUnitTests | |||||||
|             Assert.AreEqual(posts[2].Id, 2); |             Assert.AreEqual(posts[2].Id, 2); | ||||||
|             Assert.AreEqual(posts[3].Id, 1); |             Assert.AreEqual(posts[3].Id, 1); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         [TestMethod] | ||||||
|  |         public void NestedFilteringWithIdenticTypesWorks() | ||||||
|  |         { | ||||||
|  |             var model = new SieveModel() | ||||||
|  |             { | ||||||
|  |                 Filters = "(firstName|lastName)@=*2", | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |             var result = _processor.Apply(model, _comments); | ||||||
|  |             Assert.AreEqual(1, result.Count()); | ||||||
|  |  | ||||||
|  |             var comment = result.First(); | ||||||
|  |             Assert.AreEqual(comment.Id, 1); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -31,6 +31,14 @@ namespace SieveUnitTests.Services | |||||||
|             mapper.Property<Post>(p => p.OnlySortableViaFluentApi) |             mapper.Property<Post>(p => p.OnlySortableViaFluentApi) | ||||||
|                 .CanSort(); |                 .CanSort(); | ||||||
|  |  | ||||||
|  |             mapper.Property<Comment>(c => c.AuthorFirstName.Value) | ||||||
|  |                 .CanFilter() | ||||||
|  |                 .HasName("firstName"); | ||||||
|  |  | ||||||
|  |             mapper.Property<Comment>(c => c.AuthorLastName.Value) | ||||||
|  |                 .CanFilter() | ||||||
|  |                 .HasName("lastName"); | ||||||
|  |  | ||||||
|             return mapper; |             return mapper; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
							
								
								
									
										43
									
								
								SieveUnitTests/ValueObjects/Name.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								SieveUnitTests/ValueObjects/Name.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | using System; | ||||||
|  |  | ||||||
|  | namespace SieveUnitTests.ValueObjects | ||||||
|  | { | ||||||
|  |     public sealed class Name : IEquatable<Name> | ||||||
|  |     { | ||||||
|  |         public Name(string value) | ||||||
|  |         { | ||||||
|  |             if (string.IsNullOrEmpty(value)) | ||||||
|  |             { | ||||||
|  |                 throw new InvalidOperationException("Invalid string!"); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (value.Length > 50) | ||||||
|  |             { | ||||||
|  |                 throw new InvalidOperationException("String exceeds maximum name length!"); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             Value = value; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public string Value { get; private set; } | ||||||
|  |  | ||||||
|  |         public bool Equals(Name other) | ||||||
|  |         { | ||||||
|  |             if (ReferenceEquals(null, other)) return false; | ||||||
|  |             if (ReferenceEquals(this, other)) return true; | ||||||
|  |             return string.Equals(Value, other.Value); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public override bool Equals(object obj) | ||||||
|  |         { | ||||||
|  |             if (ReferenceEquals(null, obj)) return false; | ||||||
|  |             if (ReferenceEquals(this, obj)) return true; | ||||||
|  |             return obj is Name && Equals((Name) obj); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public override int GetHashCode() | ||||||
|  |         { | ||||||
|  |             return (Value != null ? Value.GetHashCode() : 0); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user