mirror of
				https://github.com/Biarity/Sieve.git
				synced 2025-11-03 18:29:02 +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.Expressions;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
namespace Sieve.Services
 | 
			
		||||
{
 | 
			
		||||
	public class SievePropertyMapper
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Dictionary<Type, Dictionary<PropertyInfo, ISievePropertyMetadata>> _map
 | 
			
		||||
            = new Dictionary<Type, Dictionary<PropertyInfo, ISievePropertyMetadata>>();
 | 
			
		||||
        private readonly Dictionary<Type, ICollection<KeyValuePair<PropertyInfo, ISievePropertyMetadata>>> _map
 | 
			
		||||
            = new Dictionary<Type, ICollection<KeyValuePair<PropertyInfo, ISievePropertyMetadata>>>();
 | 
			
		||||
 | 
			
		||||
        public PropertyFluentApi<TEntity> Property<TEntity>(Expression<Func<TEntity, object>> expression)
 | 
			
		||||
        {
 | 
			
		||||
            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);
 | 
			
		||||
@@ -65,13 +64,16 @@ namespace Sieve.Services
 | 
			
		||||
 | 
			
		||||
            private void UpdateMap()
 | 
			
		||||
            {
 | 
			
		||||
                _sievePropertyMapper._map[typeof(TEntity)][_property] = new SievePropertyMetadata()
 | 
			
		||||
                var metadata = new SievePropertyMetadata()
 | 
			
		||||
                {
 | 
			
		||||
                    Name = _name,
 | 
			
		||||
                    FullName = _fullName,
 | 
			
		||||
                    CanFilter = _canFilter,
 | 
			
		||||
                    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)
 | 
			
		||||
@@ -105,8 +107,8 @@ namespace Sieve.Services
 | 
			
		||||
                var result = _map[typeof(TEntity)]
 | 
			
		||||
                    .FirstOrDefault(kv =>
 | 
			
		||||
                    kv.Value.Name.Equals(name, isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase)
 | 
			
		||||
                    && (canSortRequired ? kv.Value.CanSort : true)
 | 
			
		||||
                    && (canFilterRequired ? kv.Value.CanFilter : true));
 | 
			
		||||
                    && (!canSortRequired || kv.Value.CanSort)
 | 
			
		||||
                    && (!canFilterRequired || kv.Value.CanFilter));
 | 
			
		||||
 | 
			
		||||
                return (result.Value?.FullName, result.Key);
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
using System;
 | 
			
		||||
using Sieve.Attributes;
 | 
			
		||||
using SieveUnitTests.ValueObjects;
 | 
			
		||||
 | 
			
		||||
namespace SieveUnitTests.Entities
 | 
			
		||||
{
 | 
			
		||||
@@ -7,6 +8,10 @@ namespace SieveUnitTests.Entities
 | 
			
		||||
    {
 | 
			
		||||
        public int Id { get; set; }
 | 
			
		||||
 | 
			
		||||
        public Name AuthorFirstName { get; set; }
 | 
			
		||||
 | 
			
		||||
        public Name AuthorLastName { get; set; }
 | 
			
		||||
 | 
			
		||||
        [Sieve(CanFilter = true, CanSort = true)]
 | 
			
		||||
        public DateTimeOffset DateCreated { get; set; } = DateTimeOffset.UtcNow;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ using Sieve.Models;
 | 
			
		||||
using Sieve.Services;
 | 
			
		||||
using SieveUnitTests.Entities;
 | 
			
		||||
using SieveUnitTests.Services;
 | 
			
		||||
using SieveUnitTests.ValueObjects;
 | 
			
		||||
 | 
			
		||||
namespace SieveUnitTests
 | 
			
		||||
{
 | 
			
		||||
@@ -63,17 +64,23 @@ namespace SieveUnitTests
 | 
			
		||||
                new Comment() {
 | 
			
		||||
                    Id = 0,
 | 
			
		||||
                    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() {
 | 
			
		||||
                    Id = 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() {
 | 
			
		||||
                    Id = 2,
 | 
			
		||||
                    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();
 | 
			
		||||
        }
 | 
			
		||||
@@ -365,5 +372,20 @@ namespace SieveUnitTests
 | 
			
		||||
            Assert.AreEqual(posts[2].Id, 2);
 | 
			
		||||
            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)
 | 
			
		||||
                .CanSort();
 | 
			
		||||
 | 
			
		||||
            mapper.Property<Comment>(c => c.AuthorFirstName.Value)
 | 
			
		||||
                .CanFilter()
 | 
			
		||||
                .HasName("firstName");
 | 
			
		||||
 | 
			
		||||
            mapper.Property<Comment>(c => c.AuthorLastName.Value)
 | 
			
		||||
                .CanFilter()
 | 
			
		||||
                .HasName("lastName");
 | 
			
		||||
 | 
			
		||||
            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