diff --git a/src/SmartWhere/Attributes/ComparativeWhereCaluseAttribute.cs b/src/SmartWhere/Attributes/ComparativeWhereCaluseAttribute.cs index 6a61b86..348ac24 100644 --- a/src/SmartWhere/Attributes/ComparativeWhereCaluseAttribute.cs +++ b/src/SmartWhere/Attributes/ComparativeWhereCaluseAttribute.cs @@ -1,15 +1,12 @@ -using SmartWhere.Enums; +namespace SmartWhere.Attributes; -namespace SmartWhere.Attributes +public class ComparativeWhereCaluseAttribute : WhereClauseAttribute { - public class ComparativeWhereCaluseAttribute : WhereClauseAttribute - { - public ComparisonOperator ComparisonOperator { get; set; } + public ComparisonOperator ComparisonOperator { get; set; } - public ComparativeWhereCaluseAttribute(ComparisonOperator comparisonOperator, LogicalOperator logicalOperator = LogicalOperator.AND) - : base(logicalOperator) => ComparisonOperator = comparisonOperator; + public ComparativeWhereCaluseAttribute(ComparisonOperator comparisonOperator, LogicalOperator logicalOperator = LogicalOperator.AND) + : base(logicalOperator) => ComparisonOperator = comparisonOperator; - public ComparativeWhereCaluseAttribute(string propertyName, ComparisonOperator comparisonOperator, LogicalOperator logicalOperator = LogicalOperator.AND) - : base(propertyName, logicalOperator) => ComparisonOperator = comparisonOperator; - } -} + public ComparativeWhereCaluseAttribute(string propertyName, ComparisonOperator comparisonOperator, LogicalOperator logicalOperator = LogicalOperator.AND) + : base(propertyName, logicalOperator) => ComparisonOperator = comparisonOperator; +} \ No newline at end of file diff --git a/src/SmartWhere/Attributes/TextualWhereClauseAttribute.cs b/src/SmartWhere/Attributes/TextualWhereClauseAttribute.cs index 710ef94..97cf0bf 100644 --- a/src/SmartWhere/Attributes/TextualWhereClauseAttribute.cs +++ b/src/SmartWhere/Attributes/TextualWhereClauseAttribute.cs @@ -1,15 +1,12 @@ -using SmartWhere.Enums; +namespace SmartWhere.Attributes; -namespace SmartWhere.Attributes +public class TextualWhereClauseAttribute : WhereClauseAttribute { - public class TextualWhereClauseAttribute : WhereClauseAttribute - { - public StringMethod StringMethod { get; set; } + public StringMethod StringMethod { get; set; } - public TextualWhereClauseAttribute(StringMethod method, LogicalOperator logicalOperator = LogicalOperator.AND) - : base(logicalOperator) => StringMethod = method; + public TextualWhereClauseAttribute(StringMethod method, LogicalOperator logicalOperator = LogicalOperator.AND) + : base(logicalOperator) => StringMethod = method; - public TextualWhereClauseAttribute(string propertyName, StringMethod method, LogicalOperator logicalOperator = LogicalOperator.AND) - : base(propertyName, logicalOperator) => StringMethod = method; - } -} + public TextualWhereClauseAttribute(string propertyName, StringMethod method, LogicalOperator logicalOperator = LogicalOperator.AND) + : base(propertyName, logicalOperator) => StringMethod = method; +} \ No newline at end of file diff --git a/src/SmartWhere/Attributes/WhereClauseAttribute.cs b/src/SmartWhere/Attributes/WhereClauseAttribute.cs index 53d8409..2a4956f 100644 --- a/src/SmartWhere/Attributes/WhereClauseAttribute.cs +++ b/src/SmartWhere/Attributes/WhereClauseAttribute.cs @@ -1,21 +1,17 @@ -using SmartWhere.Enums; -using System; +namespace SmartWhere.Attributes; -namespace SmartWhere.Attributes +[AttributeUsage(AttributeTargets.Property)] +public class WhereClauseAttribute : Attribute { - [AttributeUsage(AttributeTargets.Property)] - public class WhereClauseAttribute : Attribute - { - public string PropertyName { get; set; } + public string PropertyName { get; set; } - public LogicalOperator LogicalOperator { get; set; } + public LogicalOperator LogicalOperator { get; set; } - public WhereClauseAttribute(LogicalOperator logicalOperator = LogicalOperator.AND) => LogicalOperator = logicalOperator; + public WhereClauseAttribute(LogicalOperator logicalOperator = LogicalOperator.AND) => LogicalOperator = logicalOperator; - public WhereClauseAttribute(string propertyName, LogicalOperator logicalOperator = LogicalOperator.AND) - { - PropertyName = propertyName; - LogicalOperator = logicalOperator; - } + public WhereClauseAttribute(string propertyName, LogicalOperator logicalOperator = LogicalOperator.AND) + { + PropertyName = propertyName; + LogicalOperator = logicalOperator; } -} +} \ No newline at end of file diff --git a/src/SmartWhere/Attributes/WhereClauseClassAttribute.cs b/src/SmartWhere/Attributes/WhereClauseClassAttribute.cs index 0987709..e53f42c 100644 --- a/src/SmartWhere/Attributes/WhereClauseClassAttribute.cs +++ b/src/SmartWhere/Attributes/WhereClauseClassAttribute.cs @@ -1,9 +1,6 @@ -using System; +namespace SmartWhere.Attributes; -namespace SmartWhere.Attributes +[AttributeUsage(AttributeTargets.Property)] +public class WhereClauseClassAttribute : Attribute { - [AttributeUsage(AttributeTargets.Property)] - public class WhereClauseClassAttribute : Attribute - { - } -} +} \ No newline at end of file diff --git a/src/SmartWhere/Enums/ComparisonOperator.cs b/src/SmartWhere/Enums/ComparisonOperator.cs index d4b36e5..4c94532 100644 --- a/src/SmartWhere/Enums/ComparisonOperator.cs +++ b/src/SmartWhere/Enums/ComparisonOperator.cs @@ -1,16 +1,15 @@ -namespace SmartWhere.Enums +namespace SmartWhere.Enums; + +public enum ComparisonOperator { - public enum ComparisonOperator - { - Equal, - NotEqual, - GreaterThan, - NotGreaterThan, - GreaterThanOrEqual, - NotGreaterThanOrEqual, - LessThan, - NotLessThan, - LessThanOrEqual, - NotLessThanOrEqual - } -} + Equal, + NotEqual, + GreaterThan, + NotGreaterThan, + GreaterThanOrEqual, + NotGreaterThanOrEqual, + LessThan, + NotLessThan, + LessThanOrEqual, + NotLessThanOrEqual +} \ No newline at end of file diff --git a/src/SmartWhere/Enums/StringMethod.cs b/src/SmartWhere/Enums/StringMethod.cs index 346e44b..9242aaf 100644 --- a/src/SmartWhere/Enums/StringMethod.cs +++ b/src/SmartWhere/Enums/StringMethod.cs @@ -1,12 +1,11 @@ -namespace SmartWhere.Enums +namespace SmartWhere.Enums; + +public enum StringMethod { - public enum StringMethod - { - Contains, - NotContains, - StartsWith, - NotStartsWith, - EndsWith, - NotEndsWith - } -} + Contains, + NotContains, + StartsWith, + NotStartsWith, + EndsWith, + NotEndsWith +} \ No newline at end of file diff --git a/src/SmartWhere/Extensions/AttributeExtensions.cs b/src/SmartWhere/Extensions/AttributeExtensions.cs index 1352049..b61bc38 100644 --- a/src/SmartWhere/Extensions/AttributeExtensions.cs +++ b/src/SmartWhere/Extensions/AttributeExtensions.cs @@ -1,32 +1,27 @@ -using SmartWhere.Attributes; -using SmartWhere.Enums; -using System.Reflection; +namespace SmartWhere.Extensions; -namespace SmartWhere.Extensions +internal static class AttributeExtensions { - public static class AttributeExtensions - { - internal static WhereClauseAttribute GetWhereClauseAttribute(this MemberInfo memberInfo) => - (WhereClauseAttribute)memberInfo.GetCustomAttribute(typeof(WhereClauseAttribute), false); + internal static WhereClauseAttribute GetWhereClauseAttribute(this MemberInfo memberInfo) => + (WhereClauseAttribute)memberInfo.GetCustomAttribute(typeof(WhereClauseAttribute), false); - internal static WhereClauseClassAttribute GetWhereClauseClassAttribute(this MemberInfo memberInfo) => - (WhereClauseClassAttribute)memberInfo.GetCustomAttribute(typeof(WhereClauseClassAttribute), false); + internal static WhereClauseClassAttribute GetWhereClauseClassAttribute(this MemberInfo memberInfo) => + (WhereClauseClassAttribute)memberInfo.GetCustomAttribute(typeof(WhereClauseClassAttribute), false); - internal static MethodInfo MethodInfo(this TextualWhereClauseAttribute textualWhereClause) + internal static MethodInfo MethodInfo(this TextualWhereClauseAttribute textualWhereClause) + { + var methodName = textualWhereClause.StringMethod switch { - var methodName = textualWhereClause.StringMethod switch - { - StringMethod.Contains => textualWhereClause.StringMethod.ToString(), - StringMethod.StartsWith => textualWhereClause.StringMethod.ToString(), - StringMethod.EndsWith => textualWhereClause.StringMethod.ToString(), - StringMethod.NotContains => nameof(StringMethod.Contains), - StringMethod.NotStartsWith => nameof(StringMethod.StartsWith), - StringMethod.NotEndsWith => nameof(StringMethod.EndsWith), - _ => nameof(StringMethod.Contains) - }; + StringMethod.Contains => textualWhereClause.StringMethod.ToString(), + StringMethod.StartsWith => textualWhereClause.StringMethod.ToString(), + StringMethod.EndsWith => textualWhereClause.StringMethod.ToString(), + StringMethod.NotContains => nameof(StringMethod.Contains), + StringMethod.NotStartsWith => nameof(StringMethod.StartsWith), + StringMethod.NotEndsWith => nameof(StringMethod.EndsWith), + _ => nameof(StringMethod.Contains) + }; - return typeof(string).GetMethod(methodName, new[] { typeof(string) - }); - } + return typeof(string).GetMethod(methodName, new[] { typeof(string) + }); } -} +} \ No newline at end of file diff --git a/src/SmartWhere/Extensions/Extensions.cs b/src/SmartWhere/Extensions/Extensions.cs index e2d6414..0d84fb3 100644 --- a/src/SmartWhere/Extensions/Extensions.cs +++ b/src/SmartWhere/Extensions/Extensions.cs @@ -1,161 +1,160 @@ -using SmartWhere.Interfaces; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; +namespace SmartWhere.Extensions; -namespace SmartWhere.Extensions +internal static class Extensions { - public static class Extensions + internal static List GetWhereClauseProperties( + this IWhereClause whereClauseDto, + out object valueData) { - internal static List GetWhereClauseProperties(this IWhereClause whereClauseDto, out object valueData) - { - valueData = whereClauseDto; + valueData = whereClauseDto; - var whereClauseProperties = whereClauseDto - .GetType() - .GetProperties() - .Where(x => x.GetWhereClauseAttribute().IsNotNull()) - .ToList(); + var whereClauseProperties = whereClauseDto + .GetType() + .GetProperties() + .Where(x => x.GetWhereClauseAttribute().IsNotNull()) + .ToList(); - if (whereClauseProperties.IsNotNullAndAny()) - return whereClauseProperties; + if (whereClauseProperties.IsNotNullAndAny()) + return whereClauseProperties; - whereClauseProperties = whereClauseDto - .GetType() - .GetProperties() - .Where(x => x.GetWhereClauseClassAttribute().IsNotNull()) - .ToList(); + whereClauseProperties = whereClauseDto + .GetType() + .GetProperties() + .Where(x => x.GetWhereClauseClassAttribute().IsNotNull()) + .ToList(); - if (whereClauseProperties.IsNullOrNotAny()) - return new List(); + if (whereClauseProperties.IsNullOrNotAny()) + return new List(); - valueData = whereClauseProperties.FirstOrDefault()!.GetValue(whereClauseDto); + valueData = whereClauseProperties.FirstOrDefault()!.GetValue(whereClauseDto); - whereClauseProperties = whereClauseProperties.SelectMany(x => - x.PropertyType - .GetProperties() - .Where(p => p.GetWhereClauseAttribute() - .IsNotNull())) - .ToList(); + whereClauseProperties = whereClauseProperties.SelectMany(x => + x.PropertyType + .GetProperties() + .Where(p => p.GetWhereClauseAttribute() + .IsNotNull())) + .ToList(); - return whereClauseProperties; - } + return whereClauseProperties; + } - internal static IEnumerable<(PropertyInfo propertyInfo, Type propertyType)> PropertyInfos(this Type entityType, string propertyName) - { - var propertiesList = new List<(PropertyInfo propertyInfo, Type propertyType)>(); + internal static IEnumerable<(PropertyInfo propertyInfo, Type propertyType)> PropertyInfos( + this Type entityType, + string propertyName) + { + var propertiesList = new List<(PropertyInfo propertyInfo, Type propertyType)>(); - var entityProperties = GetEntityProperties(entityType); + var entityProperties = GetEntityProperties(entityType); - var properties = propertyName.Split('.'); + var properties = propertyName.Split('.'); - var index = -1; - var findedMainPropertyInEntity = false; + var index = -1; + var findedMainPropertyInEntity = false; - foreach (var property in properties) - { - var entityPropertInfo = entityProperties.GetPropertyInfoByType(property); + foreach (var property in properties) + { + var entityPropertInfo = entityProperties.GetPropertyInfoByType(property); - if (entityPropertInfo.propertyType.IsNotNull() && !findedMainPropertyInEntity) + if (entityPropertInfo.propertyType.IsNotNull() && !findedMainPropertyInEntity) + { + propertiesList.Add((entityPropertInfo.propertyInfo, entityPropertInfo.propertyType)); + findedMainPropertyInEntity = true; + index++; + } + else + { + if (propertiesList.IsNotNullAndAny()) { - propertiesList.Add((entityPropertInfo.propertyInfo, entityPropertInfo.propertyType)); - findedMainPropertyInEntity = true; + var propertyInfo = GetPropertyInfo(property, propertiesList[index]); + + if (propertyInfo.IsNull()) + continue; + + propertiesList.Add((propertyInfo, propertyInfo!.PropertyType)); index++; } else { - if (propertiesList.IsNotNullAndAny()) - { - var propertyInfo = GetPropertyInfo(property, propertiesList[index]); - - if (propertyInfo.IsNull()) - continue; + entityPropertInfo = entityProperties.GetPropertyInfoByInfo(property); - propertiesList.Add((propertyInfo, propertyInfo!.PropertyType)); - index++; - } - else - { - entityPropertInfo = entityProperties.GetPropertyInfoByInfo(property); - - if (entityPropertInfo.propertyType.IsNull()) - continue; + if (entityPropertInfo.propertyType.IsNull()) + continue; - propertiesList.Add((entityPropertInfo.propertyInfo, entityPropertInfo.propertyType)); - index++; - } + propertiesList.Add((entityPropertInfo.propertyInfo, entityPropertInfo.propertyType)); + index++; } } - - return propertiesList; } - private static PropertyInfo GetPropertyInfo( - string property, - (PropertyInfo propertyInfo, Type propertyType) properties) - { - PropertyInfo propertyInfo; + return propertiesList; + } - if (properties.propertyType.IsEnumarableType()) - { - propertyInfo = properties.propertyType - .GetGenericArguments() - .FirstOrDefault()! - .GetProperty(property, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase); - } - else - { - propertyInfo = properties.propertyType - .GetProperty(property, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase); - - if (propertyInfo.IsNull()) - properties.propertyType - .GetProperties() - .ToList() - .ForEach(prop => + private static PropertyInfo GetPropertyInfo( + string property, + (PropertyInfo propertyInfo, Type propertyType) properties) + { + PropertyInfo propertyInfo; + + if (properties.propertyType.IsEnumarableType()) + { + propertyInfo = properties.propertyType + .GetGenericArguments() + .FirstOrDefault()! + .GetProperty(property, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase); + } + else + { + propertyInfo = properties.propertyType + .GetProperty(property, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase); + + if (propertyInfo.IsNull()) + properties.propertyType + .GetProperties() + .ToList() + .ForEach(prop => + { + if (prop.PropertyType.IsEnumarableType()) { - if (prop.PropertyType.IsEnumarableType()) + var type = prop.PropertyType.GetGenericArguments().FirstOrDefault(); + if (string.Equals(type!.Name, property, StringComparison.OrdinalIgnoreCase)) { - var type = prop.PropertyType.GetGenericArguments().FirstOrDefault(); - if (string.Equals(type!.Name, property, StringComparison.OrdinalIgnoreCase)) - { - propertyInfo = prop; - } + propertyInfo = prop; } - else + } + else + { + if (string.Equals(prop.PropertyType.Name, property, StringComparison.OrdinalIgnoreCase)) { - if (string.Equals(prop.PropertyType.Name, property, StringComparison.OrdinalIgnoreCase)) - { - propertyInfo = prop; - } + propertyInfo = prop; } - }); - } - - return propertyInfo; + } + }); } - private static List<(PropertyInfo propertyInfo, Type propertyType)> GetEntityProperties(Type entityType) - { - var entityProperties = new List<(PropertyInfo propertyInfo, Type propertyType)>(); - - entityType.GetProperties().ToList().ForEach(x => - { - entityProperties.Add(x.PropertyType.IsEnumarableType() - ? (x, x.PropertyType.GetGenericArguments().FirstOrDefault()) - : (x, x.PropertyType)); - }); + return propertyInfo; + } - return entityProperties; - } + private static List<(PropertyInfo propertyInfo, Type propertyType)> GetEntityProperties(Type entityType) + { + var entityProperties = new List<(PropertyInfo propertyInfo, Type propertyType)>(); - private static (PropertyInfo propertyInfo, Type propertyType) GetPropertyInfoByType( - this IEnumerable<(PropertyInfo propertyInfo, Type propertyType)> entityProperties, string property) => - entityProperties.FirstOrDefault(x => string.Equals(x.propertyType.Name, property, StringComparison.OrdinalIgnoreCase)); + entityType.GetProperties().ToList().ForEach(x => + { + entityProperties.Add(x.PropertyType.IsEnumarableType() + ? (x, x.PropertyType.GetGenericArguments().FirstOrDefault()) + : (x, x.PropertyType)); + }); - private static (PropertyInfo propertyInfo, Type propertyType) GetPropertyInfoByInfo( - this IEnumerable<(PropertyInfo propertyInfo, Type propertyType)> entityProperties, string property) => - entityProperties.FirstOrDefault(x => string.Equals(x.propertyInfo.Name, property, StringComparison.OrdinalIgnoreCase)); + return entityProperties; } -} + + private static (PropertyInfo propertyInfo, Type propertyType) GetPropertyInfoByType( + this IEnumerable<(PropertyInfo propertyInfo, Type propertyType)> entityProperties, + string property) => + entityProperties.FirstOrDefault(x => string.Equals(x.propertyType.Name, property, StringComparison.OrdinalIgnoreCase)); + + private static (PropertyInfo propertyInfo, Type propertyType) GetPropertyInfoByInfo( + this IEnumerable<(PropertyInfo propertyInfo, Type propertyType)> entityProperties, + string property) => + entityProperties.FirstOrDefault(x => string.Equals(x.propertyInfo.Name, property, StringComparison.OrdinalIgnoreCase)); +} \ No newline at end of file diff --git a/src/SmartWhere/Extensions/LogicalExtensions.cs b/src/SmartWhere/Extensions/LogicalExtensions.cs index f8c9864..ba26c68 100644 --- a/src/SmartWhere/Extensions/LogicalExtensions.cs +++ b/src/SmartWhere/Extensions/LogicalExtensions.cs @@ -1,42 +1,35 @@ -using SmartWhere.Attributes; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; +namespace SmartWhere.Extensions; -namespace SmartWhere.Extensions +internal static class LogicalExtensions { - public static class LogicalExtensions - { - internal static bool IsNull(this T item) where T : class => item is null; + internal static bool IsNull(this T item) where T : class => item is null; - internal static bool IsNotNull(this T item) where T : class => item is not null; + internal static bool IsNotNull(this T item) where T : class => item is not null; - internal static bool IsNullOrNotAny(this IEnumerable items) => items is null || !items.Any(); + internal static bool IsNullOrNotAny(this IEnumerable items) => items is null || !items.Any(); - internal static bool IsNotNullAndAny(this IEnumerable items) => items is not null && items.Any(); + internal static bool IsNotNullAndAny(this IEnumerable items) => items is not null && items.Any(); - internal static bool IsNullableType(this Type type) => - type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); + internal static bool IsNullableType(this Type type) => + type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); - internal static bool IsEnumarableType(this Type type) => - type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(IEnumerable<>) || type.GetGenericTypeDefinition() == typeof(List<>)); + internal static bool IsEnumarableType(this Type type) => + type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(IEnumerable<>) || type.GetGenericTypeDefinition() == typeof(List<>)); - internal static bool PropertyNameControl(this MemberInfo memberInfo) - { - var whereClauseAttribute = (WhereClauseAttribute)memberInfo.GetCustomAttribute(typeof(WhereClauseAttribute), false); + internal static bool PropertyNameControl(this MemberInfo memberInfo) + { + var whereClauseAttribute = (WhereClauseAttribute)memberInfo.GetCustomAttribute(typeof(WhereClauseAttribute), false); - var properties = typeof(T).GetProperties(); + var properties = typeof(T).GetProperties(); - return string.IsNullOrEmpty(whereClauseAttribute!.PropertyName) - ? properties.Any(x => AreStringsEqual(x.Name, memberInfo.Name)) - : properties.Any(x => AreStringsEqual(x.Name, whereClauseAttribute!.PropertyName)); - } + return string.IsNullOrEmpty(whereClauseAttribute!.PropertyName) + ? properties.Any(x => AreStringsEqual(x.Name, memberInfo.Name)) + : properties.Any(x => AreStringsEqual(x.Name, whereClauseAttribute!.PropertyName)); + } - internal static bool ValueControl(this object value) - => value.IsNull() || string.IsNullOrEmpty(value!.ToString()); + internal static bool ValueControl(this object value) + => value.IsNull() || string.IsNullOrEmpty(value!.ToString()); - private static bool AreStringsEqual(string firstString, string secondString) - => string.Equals(firstString, secondString, StringComparison.OrdinalIgnoreCase); - } -} + private static bool AreStringsEqual(string firstString, string secondString) + => string.Equals(firstString, secondString, StringComparison.OrdinalIgnoreCase); +} \ No newline at end of file diff --git a/src/SmartWhere/GlobalUsings.cs b/src/SmartWhere/GlobalUsings.cs new file mode 100644 index 0000000..306d13e --- /dev/null +++ b/src/SmartWhere/GlobalUsings.cs @@ -0,0 +1,11 @@ +// Global using directives + +global using SmartWhere.Attributes; +global using SmartWhere.Enums; +global using SmartWhere.Extensions; +global using SmartWhere.Interfaces; +global using System; +global using System.Collections.Generic; +global using System.Linq; +global using System.Linq.Expressions; +global using System.Reflection; diff --git a/src/SmartWhere/Interfaces/IWhereClause.cs b/src/SmartWhere/Interfaces/IWhereClause.cs index abbcce6..81b8074 100644 --- a/src/SmartWhere/Interfaces/IWhereClause.cs +++ b/src/SmartWhere/Interfaces/IWhereClause.cs @@ -1,6 +1,5 @@ -namespace SmartWhere.Interfaces +namespace SmartWhere.Interfaces; + +public interface IWhereClause { - public interface IWhereClause - { - } -} +} \ No newline at end of file diff --git a/src/SmartWhere/SmartWhere.cs b/src/SmartWhere/SmartWhere.cs index 0d49766..c47bbc1 100644 --- a/src/SmartWhere/SmartWhere.cs +++ b/src/SmartWhere/SmartWhere.cs @@ -1,378 +1,367 @@ -using SmartWhere.Attributes; -using SmartWhere.Enums; -using SmartWhere.Extensions; -using SmartWhere.Interfaces; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; - -namespace SmartWhere +namespace SmartWhere; + +public static class SmartWhere { - public static class SmartWhere + private static readonly List Types = new() { - private static readonly List Types = new() - { - typeof(short), - typeof(int), - typeof(long), - typeof(short?), - typeof(int?), - typeof(long?), - typeof(decimal), - typeof(decimal?), - typeof(double), - typeof(double?), - typeof(bool), - typeof(bool?), - typeof(DateTime), - typeof(DateTime?) - }; - - public static IQueryable Where(this IQueryable source, IWhereClause whereClauseDto) - { - var whereClauseProperties = whereClauseDto.GetWhereClauseProperties(out var valueData); - - if (whereClauseProperties.IsNullOrNotAny()) - return source.Where(x => true); - - Expression comparison = null; - - var parameter = Expression.Parameter(typeof(T), typeof(T).Name.ToLower()); - - foreach (var whereClauseProperty in whereClauseProperties!) - { - var propertyValue = whereClauseProperty!.GetValue(valueData); - - if (propertyValue.ValueControl()) - continue; + typeof(short), + typeof(int), + typeof(long), + typeof(short?), + typeof(int?), + typeof(long?), + typeof(decimal), + typeof(decimal?), + typeof(double), + typeof(double?), + typeof(bool), + typeof(bool?), + typeof(DateTime), + typeof(DateTime?) + }; + + public static IQueryable Where(this IQueryable source, IWhereClause whereClauseDto) + { + var whereClauseProperties = whereClauseDto.GetWhereClauseProperties(out var valueData); - comparison = GetComparison( - parameter, - whereClauseProperty, - propertyValue, - comparison); - } + if (whereClauseProperties.IsNullOrNotAny()) + return source.Where(x => true); - return comparison.IsNotNull() - ? source.Where(Expression.Lambda>(comparison!, parameter)) - : source.Where(x => true); - } + Expression comparison = null; - private static Expression GetComparison( - Expression parameter, - PropertyInfo whereClauseProperty, - object propertyValue, - Expression comparison) => - whereClauseProperty.PropertyNameControl() - ? BasicComparison( - parameter, - whereClauseProperty, - propertyValue, - comparison) - : ComplexComparison( - parameter, - whereClauseProperty, - propertyValue, - comparison); + var parameter = Expression.Parameter(typeof(T), typeof(T).Name.ToLower()); - private static Expression BasicComparison( - Expression parameter, - PropertyInfo whereClauseProperty, - object propertyValue, - Expression comparison) + foreach (var whereClauseProperty in whereClauseProperties!) { - var whereClauseAttribute = whereClauseProperty.GetWhereClauseAttribute(); + var propertyValue = whereClauseProperty!.GetValue(valueData); - var methodExpression = MethodExpressionForBasicComparison( + if (propertyValue.ValueControl()) + continue; + + comparison = GetComparison( parameter, - whereClauseAttribute, whereClauseProperty, - propertyValue); - - return comparison.IsNull() - ? methodExpression - : whereClauseAttribute.LogicalOperator == LogicalOperator.AND - ? Expression.And(comparison, methodExpression!) - : Expression.Or(comparison, methodExpression!); + propertyValue, + comparison); } - private static Expression MethodExpressionForBasicComparison( - Expression parameter, - WhereClauseAttribute whereClauseAttribute, - PropertyInfo whereClauseProperty, - object propertyValue) - { - var memberExpression = string.IsNullOrEmpty(whereClauseAttribute!.PropertyName) - ? Expression.Property(parameter, whereClauseProperty.Name) - : Expression.Property(parameter, whereClauseAttribute.PropertyName); + return comparison.IsNotNull() + ? source.Where(Expression.Lambda>(comparison!, parameter)) + : source.Where(x => true); + } - var expression = SetExpressionByNullableType( + private static Expression GetComparison( + Expression parameter, + PropertyInfo whereClauseProperty, + object propertyValue, + Expression comparison) => + whereClauseProperty.PropertyNameControl() + ? BasicComparison( + parameter, whereClauseProperty, propertyValue, - memberExpression.Type); - - return SetMethodExpressionByType( - memberExpression, - whereClauseAttribute, - expression); - } - - private static Expression SetExpressionByNullableType( - PropertyInfo whereClauseProperty, - object propertyValue, - Type memberExpressionType) - { - if (!whereClauseProperty.PropertyType.IsNullableType()) - return Expression.Constant(propertyValue); + comparison) + : ComplexComparison( + parameter, + whereClauseProperty, + propertyValue, + comparison); - var constantExpression = Expression.Constant(Convert.ChangeType(propertyValue, whereClauseProperty.PropertyType.GenericTypeArguments[0])); - return Expression.Convert(constantExpression, memberExpressionType); + private static Expression BasicComparison( + Expression parameter, + PropertyInfo whereClauseProperty, + object propertyValue, + Expression comparison) + { + var whereClauseAttribute = whereClauseProperty.GetWhereClauseAttribute(); + + var methodExpression = MethodExpressionForBasicComparison( + parameter, + whereClauseAttribute, + whereClauseProperty, + propertyValue); + + return comparison.IsNull() + ? methodExpression + : whereClauseAttribute.LogicalOperator == LogicalOperator.AND + ? Expression.And(comparison, methodExpression!) + : Expression.Or(comparison, methodExpression!); + } - } + private static Expression MethodExpressionForBasicComparison( + Expression parameter, + WhereClauseAttribute whereClauseAttribute, + PropertyInfo whereClauseProperty, + object propertyValue) + { + var memberExpression = string.IsNullOrEmpty(whereClauseAttribute!.PropertyName) + ? Expression.Property(parameter, whereClauseProperty.Name) + : Expression.Property(parameter, whereClauseAttribute.PropertyName); + + var expression = SetExpressionByNullableType( + whereClauseProperty, + propertyValue, + memberExpression.Type); + + return SetMethodExpressionByType( + memberExpression, + whereClauseAttribute, + expression); + } - private static Expression SetMethodExpressionByType( - Expression memberExpression, - WhereClauseAttribute whereClauseAttribute, - Expression expression) - { + private static Expression SetExpressionByNullableType( + PropertyInfo whereClauseProperty, + object propertyValue, + Type memberExpressionType) + { + if (!whereClauseProperty.PropertyType.IsNullableType()) + return Expression.Constant(propertyValue); - if (memberExpression.Type == typeof(string)) - { - if (whereClauseAttribute.GetType().BaseType != typeof(WhereClauseAttribute)) - return Expression.Equal(memberExpression, expression); + var constantExpression = Expression.Constant(Convert.ChangeType(propertyValue, whereClauseProperty.PropertyType.GenericTypeArguments[0])); + return Expression.Convert(constantExpression, memberExpressionType); - var textualWhereClause = (TextualWhereClauseAttribute)whereClauseAttribute; + } - return textualWhereClause.StringMethod switch - { - StringMethod.Contains => Expression.Call(memberExpression, textualWhereClause.MethodInfo(), expression), - StringMethod.StartsWith => Expression.Call(memberExpression, textualWhereClause.MethodInfo(), expression), - StringMethod.EndsWith => Expression.Call(memberExpression, textualWhereClause.MethodInfo(), expression), - StringMethod.NotContains => Expression.Not(Expression.Call(memberExpression, textualWhereClause.MethodInfo(), expression)), - StringMethod.NotStartsWith => Expression.Not(Expression.Call(memberExpression, textualWhereClause.MethodInfo(), expression)), - StringMethod.NotEndsWith => Expression.Not(Expression.Call(memberExpression, textualWhereClause.MethodInfo(), expression)), - _ => Expression.Equal(memberExpression, expression) - }; - } + private static Expression SetMethodExpressionByType( + Expression memberExpression, + WhereClauseAttribute whereClauseAttribute, + Expression expression) + { - if (!Types.Contains(memberExpression.Type)) + if (memberExpression.Type == typeof(string)) + { + if (whereClauseAttribute.GetType().BaseType != typeof(WhereClauseAttribute)) return Expression.Equal(memberExpression, expression); - if (whereClauseAttribute.GetType().BaseType == typeof(WhereClauseAttribute)) + var textualWhereClause = (TextualWhereClauseAttribute)whereClauseAttribute; + + return textualWhereClause.StringMethod switch { - return ((ComparativeWhereCaluseAttribute)whereClauseAttribute).ComparisonOperator switch - { - ComparisonOperator.Equal => Expression.Equal(memberExpression, expression), - ComparisonOperator.NotEqual => Expression.NotEqual(memberExpression, expression), - ComparisonOperator.GreaterThan => Expression.GreaterThan(memberExpression, expression), - ComparisonOperator.NotGreaterThan => Expression.Not(Expression.GreaterThan(memberExpression, expression)), - ComparisonOperator.GreaterThanOrEqual => Expression.GreaterThanOrEqual(memberExpression, expression), - ComparisonOperator.NotGreaterThanOrEqual => Expression.Not(Expression.GreaterThanOrEqual(memberExpression, expression)), - ComparisonOperator.LessThan => Expression.LessThan(memberExpression, expression), - ComparisonOperator.NotLessThan => Expression.Not(Expression.LessThan(memberExpression, expression)), - ComparisonOperator.LessThanOrEqual => Expression.LessThanOrEqual(memberExpression, expression), - ComparisonOperator.NotLessThanOrEqual => Expression.Not(Expression.LessThanOrEqual(memberExpression, expression)), - _ => Expression.Equal(memberExpression, expression) - }; - } + StringMethod.Contains => Expression.Call(memberExpression, textualWhereClause.MethodInfo(), expression), + StringMethod.StartsWith => Expression.Call(memberExpression, textualWhereClause.MethodInfo(), expression), + StringMethod.EndsWith => Expression.Call(memberExpression, textualWhereClause.MethodInfo(), expression), + StringMethod.NotContains => Expression.Not(Expression.Call(memberExpression, textualWhereClause.MethodInfo(), expression)), + StringMethod.NotStartsWith => Expression.Not(Expression.Call(memberExpression, textualWhereClause.MethodInfo(), expression)), + StringMethod.NotEndsWith => Expression.Not(Expression.Call(memberExpression, textualWhereClause.MethodInfo(), expression)), + _ => Expression.Equal(memberExpression, expression) + }; + } + if (!Types.Contains(memberExpression.Type)) return Expression.Equal(memberExpression, expression); + if (whereClauseAttribute.GetType().BaseType == typeof(WhereClauseAttribute)) + { + return ((ComparativeWhereCaluseAttribute)whereClauseAttribute).ComparisonOperator switch + { + ComparisonOperator.Equal => Expression.Equal(memberExpression, expression), + ComparisonOperator.NotEqual => Expression.NotEqual(memberExpression, expression), + ComparisonOperator.GreaterThan => Expression.GreaterThan(memberExpression, expression), + ComparisonOperator.NotGreaterThan => Expression.Not(Expression.GreaterThan(memberExpression, expression)), + ComparisonOperator.GreaterThanOrEqual => Expression.GreaterThanOrEqual(memberExpression, expression), + ComparisonOperator.NotGreaterThanOrEqual => Expression.Not(Expression.GreaterThanOrEqual(memberExpression, expression)), + ComparisonOperator.LessThan => Expression.LessThan(memberExpression, expression), + ComparisonOperator.NotLessThan => Expression.Not(Expression.LessThan(memberExpression, expression)), + ComparisonOperator.LessThanOrEqual => Expression.LessThanOrEqual(memberExpression, expression), + ComparisonOperator.NotLessThanOrEqual => Expression.Not(Expression.LessThanOrEqual(memberExpression, expression)), + _ => Expression.Equal(memberExpression, expression) + }; } - private static Expression ComplexComparison( - Expression baseParameter, - PropertyInfo whereClauseProperty, - object propertyValue, - Expression comparison) - { - var whereClauseAttribute = whereClauseProperty.GetWhereClauseAttribute(); + return Expression.Equal(memberExpression, expression); + + } + + private static Expression ComplexComparison( + Expression baseParameter, + PropertyInfo whereClauseProperty, + object propertyValue, + Expression comparison) + { + var whereClauseAttribute = whereClauseProperty.GetWhereClauseAttribute(); + + var properties = typeof(T) + .PropertyInfos(whereClauseAttribute!.PropertyName) + .ToList(); - var properties = typeof(T) - .PropertyInfos(whereClauseAttribute!.PropertyName) - .ToList(); + MemberExpression lastMember = null; + MemberExpression lastEnumerableMember = null; + Type currentType = null; + ParameterExpression parameterExpression = null; + var index = 0; - MemberExpression lastMember = null; - MemberExpression lastEnumerableMember = null; - Type currentType = null; - ParameterExpression parameterExpression = null; - var index = 0; + foreach (var (propertyInfo, propertyType) in properties) + { - foreach (var (propertyInfo, propertyType) in properties) + if (!propertyType.Namespace!.StartsWith("System") || + propertyInfo.PropertyType!.IsEnumarableType()) { + currentType = currentType.IsNull() + ? propertyInfo.PropertyType + : currentType; - if (!propertyType.Namespace!.StartsWith("System") || - propertyInfo.PropertyType!.IsEnumarableType()) - { - currentType = currentType.IsNull() - ? propertyInfo.PropertyType - : currentType; + lastEnumerableMember = SetLastEnumerableMember( + lastEnumerableMember, + lastMember, + baseParameter, + propertyInfo.Name); - lastEnumerableMember = SetLastEnumerableMember( - lastEnumerableMember, - lastMember, - baseParameter, - propertyInfo.Name); + var type = SetType(currentType, properties[index].propertyType); - var type = SetType(currentType, properties[index].propertyType); + parameterExpression = SetParameterExpression( + currentType, + type, + parameterExpression); - parameterExpression = SetParameterExpression( - currentType, - type, - parameterExpression); + lastMember = SetLastMember( + lastMember, + baseParameter, + propertyInfo, + currentType, + parameterExpression); - lastMember = SetLastMember( - lastMember, - baseParameter, - propertyInfo, - currentType, - parameterExpression); + currentType = propertyInfo.PropertyType; + } + else + { + var type = SetType(currentType, properties[index].propertyType); + + var expression = SetParameterExpression( + currentType, + type, + parameterExpression); + + var memberExpression = SetMemberExpression( + currentType, + expression, + propertyInfo, + lastMember); + + var methodExpression = MethodExpressionForComplexComparison( + currentType, + propertyType, + propertyValue, + memberExpression, + whereClauseAttribute, + whereClauseProperty, + lastMember, + expression, + lastEnumerableMember); - currentType = propertyInfo.PropertyType; - } - else + if (lastEnumerableMember.IsNotNull() && lastEnumerableMember!.Type.IsEnumarableType()) { - var type = SetType(currentType, properties[index].propertyType); - - var expression = SetParameterExpression( - currentType, - type, - parameterExpression); - - var memberExpression = SetMemberExpression( - currentType, - expression, - propertyInfo, - lastMember); - - var methodExpression = MethodExpressionForComplexComparison( - currentType, - propertyType, - propertyValue, - memberExpression, - whereClauseAttribute, - whereClauseProperty, - lastMember, - expression, - lastEnumerableMember); - - if (lastEnumerableMember.IsNotNull() && lastEnumerableMember!.Type.IsEnumarableType()) - { - methodExpression = Expression.Call(typeof(Enumerable), - "Any", - new[] { lastEnumerableMember.Type.GetGenericArguments().FirstOrDefault() }, - lastEnumerableMember, - Expression.Lambda(methodExpression!, parameterExpression!)); - } - - comparison = comparison.IsNull() - ? methodExpression - : whereClauseAttribute.LogicalOperator == LogicalOperator.AND - ? Expression.And(comparison, methodExpression!) - : Expression.Or(comparison, methodExpression!); - - index++; + methodExpression = Expression.Call(typeof(Enumerable), + "Any", + new[] { lastEnumerableMember.Type.GetGenericArguments().FirstOrDefault() }, + lastEnumerableMember, + Expression.Lambda(methodExpression!, parameterExpression!)); } - } - return comparison; - } + comparison = comparison.IsNull() + ? methodExpression + : whereClauseAttribute.LogicalOperator == LogicalOperator.AND + ? Expression.And(comparison, methodExpression!) + : Expression.Or(comparison, methodExpression!); - private static MemberExpression SetLastEnumerableMember( - MemberExpression lastEnumerableMember, - MemberExpression lastMember, - Expression baseParameter, - string propertyInfoName) => - lastMember.IsNull() - ? Expression.Property(baseParameter, propertyInfoName) - : lastEnumerableMember; - - private static MemberExpression SetLastMember( - MemberExpression lastMember, - Expression baseParameter, - MemberInfo propertyInfo, - Type currentType, - Expression parameterExpression) - { - if (lastMember.IsNull()) - { - return Expression.Property(baseParameter, propertyInfo.Name); + index++; } - - return currentType.IsEnumarableType() - ? Expression.MakeMemberAccess(parameterExpression, propertyInfo) - : Expression.Property(lastMember!, propertyInfo.Name); } - private static Type SetType( - Type currentType, - Type propertyType) => - currentType.IsEnumarableType() - ? currentType!.GetGenericArguments().FirstOrDefault() - : propertyType; - - private static ParameterExpression SetParameterExpression( - Type currentType, - Type type, - ParameterExpression parameterExpression) - { - if (currentType.IsEnumarableType()) - { - return Expression.Parameter(type!, type!.Name.ToLower()); - } + return comparison; + } - return parameterExpression.IsNull() - ? Expression.Parameter(type, type.Name.ToLower()) - : parameterExpression; + private static MemberExpression SetLastEnumerableMember( + MemberExpression lastEnumerableMember, + MemberExpression lastMember, + Expression baseParameter, + string propertyInfoName) => + lastMember.IsNull() + ? Expression.Property(baseParameter, propertyInfoName) + : lastEnumerableMember; + + private static MemberExpression SetLastMember( + MemberExpression lastMember, + Expression baseParameter, + MemberInfo propertyInfo, + Type currentType, + Expression parameterExpression) + { + if (lastMember.IsNull()) + { + return Expression.Property(baseParameter, propertyInfo.Name); } - private static MemberExpression SetMemberExpression( - Type currentType, - Expression parameterExpression, - MemberInfo propertyInfo, - Expression lastMember) => - currentType.IsEnumarableType() - ? Expression.MakeMemberAccess(parameterExpression, propertyInfo) - : Expression.MakeMemberAccess(lastMember, propertyInfo); - - private static Expression MethodExpressionForComplexComparison( - Type currentType, - Type propertyType, - object propertyValue, - Expression memberExpression, - WhereClauseAttribute whereClauseAttribute, - PropertyInfo whereClauseProperty, - Expression lastMember, - ParameterExpression parameterExpression, - MemberExpression lastEnumerableMember) + + return currentType.IsEnumarableType() + ? Expression.MakeMemberAccess(parameterExpression, propertyInfo) + : Expression.Property(lastMember!, propertyInfo.Name); + } + + private static Type SetType( + Type currentType, + Type propertyType) => + currentType.IsEnumarableType() + ? currentType!.GetGenericArguments().FirstOrDefault() + : propertyType; + + private static ParameterExpression SetParameterExpression( + Type currentType, + Type type, + ParameterExpression parameterExpression) + { + if (currentType.IsEnumarableType()) { - var expression = SetExpressionByNullableType(whereClauseProperty, propertyValue, memberExpression.Type); + return Expression.Parameter(type!, type!.Name.ToLower()); + } - var methodExpression = SetMethodExpressionByType(memberExpression, whereClauseAttribute, expression); + return parameterExpression.IsNull() + ? Expression.Parameter(type, type.Name.ToLower()) + : parameterExpression; + } + private static MemberExpression SetMemberExpression( + Type currentType, + Expression parameterExpression, + MemberInfo propertyInfo, + Expression lastMember) => + currentType.IsEnumarableType() + ? Expression.MakeMemberAccess(parameterExpression, propertyInfo) + : Expression.MakeMemberAccess(lastMember, propertyInfo); + + private static Expression MethodExpressionForComplexComparison( + Type currentType, + Type propertyType, + object propertyValue, + Expression memberExpression, + WhereClauseAttribute whereClauseAttribute, + PropertyInfo whereClauseProperty, + Expression lastMember, + ParameterExpression parameterExpression, + MemberExpression lastEnumerableMember) + { + var expression = SetExpressionByNullableType(whereClauseProperty, propertyValue, memberExpression.Type); - if (currentType.IsEnumarableType()) - { - return Expression.Call(typeof(Enumerable), - "Any", - new[] { lastMember.Type.GetGenericArguments().FirstOrDefault() }, - lastMember, - Expression.Lambda(methodExpression, parameterExpression)); - } + var methodExpression = SetMethodExpressionByType(memberExpression, whereClauseAttribute, expression); - if (propertyType != typeof(string) && !Types.Contains(propertyType)) - return Expression.Equal(memberExpression, Expression.Constant(propertyValue)); + if (currentType.IsEnumarableType()) + { + return Expression.Call(typeof(Enumerable), + "Any", + new[] { lastMember.Type.GetGenericArguments().FirstOrDefault() }, + lastMember, + Expression.Lambda(methodExpression, parameterExpression)); + } - if (lastEnumerableMember.IsNotNull() && lastEnumerableMember.Type.IsEnumarableType()) - { - return Expression.Call(typeof(Enumerable), - "Any", - new[] { lastEnumerableMember.Type.GetGenericArguments().FirstOrDefault() }, - lastEnumerableMember, - Expression.Lambda(methodExpression!, parameterExpression)); - } + if (propertyType != typeof(string) && !Types.Contains(propertyType)) + return Expression.Equal(memberExpression, Expression.Constant(propertyValue)); - return SetMethodExpressionByType(memberExpression, whereClauseAttribute, Expression.Constant(propertyValue)); + if (lastEnumerableMember.IsNotNull() && lastEnumerableMember.Type.IsEnumarableType()) + { + return Expression.Call(typeof(Enumerable), + "Any", + new[] { lastEnumerableMember.Type.GetGenericArguments().FirstOrDefault() }, + lastEnumerableMember, + Expression.Lambda(methodExpression!, parameterExpression)); } + + return SetMethodExpressionByType(memberExpression, whereClauseAttribute, Expression.Constant(propertyValue)); } } \ No newline at end of file diff --git a/src/SmartWhere/SmartWhere.csproj b/src/SmartWhere/SmartWhere.csproj index 8998010..1cceade 100644 --- a/src/SmartWhere/SmartWhere.csproj +++ b/src/SmartWhere/SmartWhere.csproj @@ -2,7 +2,7 @@ SmartWhere - 2.1.1.2 + 2.2.0 Barış Yerlikaya Barış Yerlikaya SmartWhere