diff --git a/StyleCop.ruleset b/StyleCop.ruleset
index 792caf94fa32e4172e842c8bcc7ec7c733a92db7..7f3c0343b4b12f65f394e4d730de38453e59bb4c 100644
--- a/StyleCop.ruleset
+++ b/StyleCop.ruleset
@@ -574,6 +574,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Strainer.AspNetCore/Extensions/DependencyInjection/StrainerServiceCollectionExtensions.cs b/src/Strainer.AspNetCore/Extensions/DependencyInjection/StrainerServiceCollectionExtensions.cs
index 7b948d8aa60d19946960f7155ff377815e69e8d4..9894025c3b63d76b379fc114c37b27fbac0127bb 100644
--- a/src/Strainer.AspNetCore/Extensions/DependencyInjection/StrainerServiceCollectionExtensions.cs
+++ b/src/Strainer.AspNetCore/Extensions/DependencyInjection/StrainerServiceCollectionExtensions.cs
@@ -5,6 +5,7 @@ using Fluorite.Strainer.Services.Configuration;
using Fluorite.Strainer.Services.Conversion;
using Fluorite.Strainer.Services.Filtering;
using Fluorite.Strainer.Services.Filtering.Steps;
+using Fluorite.Strainer.Services.Linq;
using Fluorite.Strainer.Services.Metadata;
using Fluorite.Strainer.Services.Metadata.Attributes;
using Fluorite.Strainer.Services.Metadata.FluentApi;
@@ -46,10 +47,6 @@ public static class StrainerServiceCollectionExtensions
///
/// is .
///
- ///
- /// Another Strainer processor was already registered within the
- /// current .
- ///
public static IServiceCollection AddStrainer(
this IServiceCollection services,
ServiceLifetime serviceLifetime = DefaultServiceLifetime)
@@ -86,10 +83,6 @@ public static class StrainerServiceCollectionExtensions
///
/// is .
///
- ///
- /// Another Strainer processor was already registered within the
- /// current .
- ///
public static IServiceCollection AddStrainer(
this IServiceCollection services,
Assembly[] assembliesToScan,
@@ -100,7 +93,7 @@ public static class StrainerServiceCollectionExtensions
var moduleTypes = GetModuleTypesFromAssemblies(assembliesToScan);
- services.AddSingleton(new AssemblySourceProvider(assembliesToScan));
+ services.TryAddSingleton(new AssemblySourceProvider(assembliesToScan));
return services.AddStrainer(moduleTypes, serviceLifetime);
}
@@ -128,10 +121,6 @@ public static class StrainerServiceCollectionExtensions
///
/// is .
///
- ///
- /// Another Strainer processor was already registered within the
- /// current .
- ///
public static IServiceCollection AddStrainer(
this IServiceCollection services,
IReadOnlyCollection moduleTypes,
@@ -168,10 +157,6 @@ public static class StrainerServiceCollectionExtensions
///
/// is .
///
- ///
- /// Another Strainer processor was already registered within the
- /// current .
- ///
public static IServiceCollection AddStrainer(
this IServiceCollection services,
IConfiguration configuration,
@@ -212,10 +197,6 @@ public static class StrainerServiceCollectionExtensions
///
/// is .
///
- ///
- /// Another Strainer processor was already registered within the
- /// current .
- ///
public static IServiceCollection AddStrainer(
this IServiceCollection services,
IConfiguration configuration,
@@ -265,10 +246,6 @@ public static class StrainerServiceCollectionExtensions
///
/// is .
///
- ///
- /// Another Strainer processor was already registered within the
- /// current .
- ///
public static IServiceCollection AddStrainer(
this IServiceCollection services,
IConfiguration configuration,
@@ -280,7 +257,7 @@ public static class StrainerServiceCollectionExtensions
Guard.Against.Null(assembliesToScan);
services.Configure(configuration);
- services.AddSingleton(new AssemblySourceProvider(assembliesToScan));
+ services.TryAddSingleton(new AssemblySourceProvider(assembliesToScan));
return services.AddStrainer(assembliesToScan, serviceLifetime);
}
@@ -308,10 +285,6 @@ public static class StrainerServiceCollectionExtensions
///
/// is .
///
- ///
- /// Another Strainer processor was already registered within the
- /// current .
- ///
public static IServiceCollection AddStrainer(
this IServiceCollection services,
Action configure,
@@ -352,10 +325,6 @@ public static class StrainerServiceCollectionExtensions
///
/// is .
///
- ///
- /// Another Strainer processor was already registered within the
- /// current .
- ///
public static IServiceCollection AddStrainer(
this IServiceCollection services,
Action configure,
@@ -405,10 +374,6 @@ public static class StrainerServiceCollectionExtensions
///
/// is .
///
- ///
- /// Another Strainer processor was already registered within the
- /// current .
- ///
public static IServiceCollection AddStrainer(
this IServiceCollection services,
Action configure,
@@ -420,7 +385,7 @@ public static class StrainerServiceCollectionExtensions
Guard.Against.Null(assembliesToScan);
services.AddOptions().Configure(configure);
- services.AddSingleton(new AssemblySourceProvider(assembliesToScan));
+ services.TryAddSingleton(new AssemblySourceProvider(assembliesToScan));
return services.AddStrainer(assembliesToScan, serviceLifetime);
}
@@ -430,95 +395,89 @@ public static class StrainerServiceCollectionExtensions
IReadOnlyCollection moduleTypes,
ServiceLifetime serviceLifetime)
{
- if (services.Any(d => d.ServiceType == typeof(IStrainerProcessor)))
- {
- throw new InvalidOperationException(
- "Unable to registrer Strainer services because they have been registered already.");
- }
-
services.AddOptions();
if (serviceLifetime == ServiceLifetime.Singleton)
{
- services.Add(serviceLifetime);
+ services.TryAdd(serviceLifetime);
}
else
{
- services.Add(serviceLifetime);
+ services.TryAdd(serviceLifetime);
}
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
-
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
-
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
-
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
services.TryAddSingleton();
- services.Add(serviceLifetime);
-
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
-
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
-
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
-
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
- services.Add(serviceLifetime);
-
- services.AddSingleton(serviceProvider =>
+ services.TryAdd(serviceLifetime);
+
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAddEnumerable(serviceLifetime);
+ services.TryAddEnumerable(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+
+ services.TryAdd(serviceLifetime);
+ services.TryAdd(serviceLifetime);
+
+ services.TryAddSingleton(serviceProvider =>
{
using var scope = serviceProvider.CreateScope();
var configurationFactory = scope.ServiceProvider.GetRequiredService();
@@ -538,12 +497,20 @@ public static class StrainerServiceCollectionExtensions
});
}
- private static void Add(
+ private static void TryAdd(
+ this IServiceCollection services,
+ ServiceLifetime serviceLifetime)
+ where TImplementationType : TServiceType
+ {
+ services.TryAdd(new ServiceDescriptor(typeof(TServiceType), typeof(TImplementationType), serviceLifetime));
+ }
+
+ private static void TryAddEnumerable(
this IServiceCollection services,
ServiceLifetime serviceLifetime)
- where TImplementationType : TServiceType
+ where TImplementationType : TServiceType
{
- services.Add(new ServiceDescriptor(typeof(TServiceType), typeof(TImplementationType), serviceLifetime));
+ services.TryAddEnumerable(new ServiceDescriptor(typeof(TServiceType), typeof(TImplementationType), serviceLifetime));
}
private static List GetModuleTypesFromAssemblies(IReadOnlyCollection assemblies)
diff --git a/src/Strainer.AspNetCore/Strainer.AspNetCore.csproj b/src/Strainer.AspNetCore/Strainer.AspNetCore.csproj
index cbf04954a4a7f9d5f5ccca00bfb2f1d292b6df31..c55db2b9ba8335c05ee72634e9355e5dc7b254b6 100644
--- a/src/Strainer.AspNetCore/Strainer.AspNetCore.csproj
+++ b/src/Strainer.AspNetCore/Strainer.AspNetCore.csproj
@@ -6,7 +6,7 @@
Fluorite.Strainer.AspNetCore
Fluorite.Strainer.AspNetCore
Fluorite
- 4.0.0-preview3
+ 4.0.0-preview4
Extensions for using Strainer with ASP.NET Core.
diff --git a/src/Strainer.ExampleWebApi/Strainer.ExampleWebApi.csproj b/src/Strainer.ExampleWebApi/Strainer.ExampleWebApi.csproj
index a9e90afd77b17ee1dae7c8b0e89c2a1f6f71113a..1f91954e7d669e72534833a5797a349bd402d92b 100644
--- a/src/Strainer.ExampleWebApi/Strainer.ExampleWebApi.csproj
+++ b/src/Strainer.ExampleWebApi/Strainer.ExampleWebApi.csproj
@@ -21,7 +21,7 @@
-
+
diff --git a/src/Strainer/Attributes/StrainerObjectAttribute.cs b/src/Strainer/Attributes/StrainerObjectAttribute.cs
index 2c4d85891f884799c060fb5d3c3476f8c4f9c59a..4cdc7eb4c38cbd276f308c44fdd8bb1659d13370 100644
--- a/src/Strainer/Attributes/StrainerObjectAttribute.cs
+++ b/src/Strainer/Attributes/StrainerObjectAttribute.cs
@@ -1,4 +1,5 @@
using Fluorite.Strainer.Models.Metadata;
+using Fluorite.Strainer.Models.Sorting;
using System.Reflection;
namespace Fluorite.Strainer.Attributes;
@@ -35,29 +36,27 @@ public class StrainerObjectAttribute : Attribute, IObjectMetadata
///
/// Property name being default sorting property for marked object.
///
- ///
- /// A value indicating whether default sorting way
- /// for marked object is descending.
+ ///
+ /// A default sorting way for marked object.
///
///
/// is ,
/// empty or contains only whitespace characters.
///
- public StrainerObjectAttribute(string defaultSortingPropertyName, bool isDefaultSortingDescending) : this(defaultSortingPropertyName)
+ public StrainerObjectAttribute(string defaultSortingPropertyName, SortingWay defaultSortingWay) : this(defaultSortingPropertyName)
{
- IsDefaultSortingDescending = isDefaultSortingDescending;
+ DefaultSortingWay = defaultSortingWay;
}
///
public string DefaultSortingPropertyName { get; }
///
- /// Gets a value indicating whether default
- /// sorting way for marked object is descending.
+ /// Gets default sorting way used when applying sorting using default sorting property.
///
- /// Defaults to .
+ /// Defaults to .
///
- public bool IsDefaultSortingDescending { get; } = false;
+ public SortingWay? DefaultSortingWay { get; }
///
/// Gets or sets a value indicating whether marked
diff --git a/src/Strainer/Attributes/StrainerPropertyAttribute.cs b/src/Strainer/Attributes/StrainerPropertyAttribute.cs
index 971fd8a4a26910bd27e63e170b5d5471dccad830..493bbd290c8e30bed801e6a4a2ec3ee12b7c3f8d 100644
--- a/src/Strainer/Attributes/StrainerPropertyAttribute.cs
+++ b/src/Strainer/Attributes/StrainerPropertyAttribute.cs
@@ -1,4 +1,5 @@
using Fluorite.Strainer.Models.Metadata;
+using Fluorite.Strainer.Models.Sorting;
using System.Reflection;
namespace Fluorite.Strainer.Attributes;
@@ -35,12 +36,12 @@ public class StrainerPropertyAttribute : Attribute, IPropertyMetadata
public bool IsDefaultSorting { get; set; } = false;
///
- /// Gets or sets a value indicating whether default
- /// sorting should be performed in a descending way.
+ /// Gets or sets default sorting way used when related property is marked
+ /// as a default sorting property.
///
- /// Defaults to .
+ /// Defaults to .
///
- public bool IsDefaultSortingDescending { get; set; } = false;
+ public SortingWay? DefaultSortingWay { get; set; } = null;
///
/// Gets or sets a value indicating whether related
@@ -58,9 +59,7 @@ public class StrainerPropertyAttribute : Attribute, IPropertyMetadata
///
public bool IsSortable { get; set; } = true;
- ///
- /// Gets the real name of related property.
- ///
+ ///
public string Name => PropertyInfo!.Name;
///
diff --git a/src/Strainer/Collections/ReadOnlyHashSet.cs b/src/Strainer/Collections/ReadOnlyHashSet.cs
index af2c5d7b049388856068045aa6da5ea112fb9b4b..01b9de81545b3367f9a925227b9cd6ffbe0367ac 100644
--- a/src/Strainer/Collections/ReadOnlyHashSet.cs
+++ b/src/Strainer/Collections/ReadOnlyHashSet.cs
@@ -1,4 +1,5 @@
using System.Collections;
+using System.Diagnostics;
namespace Fluorite.Strainer.Collections;
@@ -8,6 +9,7 @@ namespace Fluorite.Strainer.Collections;
///
/// The type of elements in the hash set.
///
+[DebuggerDisplay(nameof(Count) + " = {" + nameof(Count) + ",nq}")]
public class ReadOnlyHashSet : IReadOnlySet, IReadOnlyCollection, IEnumerable, IEnumerable
{
private readonly HashSet _set;
diff --git a/src/Strainer/Exceptions/StrainerException.cs b/src/Strainer/Exceptions/StrainerException.cs
index 48f0d369bbf85414d493e1c065af7c740a7149a5..e3455540616ed04326054d8c6651064907be0c7b 100644
--- a/src/Strainer/Exceptions/StrainerException.cs
+++ b/src/Strainer/Exceptions/StrainerException.cs
@@ -1,6 +1,4 @@
-using System.Runtime.Serialization;
-
-namespace Fluorite.Strainer.Exceptions;
+namespace Fluorite.Strainer.Exceptions;
public class StrainerException : Exception
{
@@ -18,9 +16,4 @@ public class StrainerException : Exception
{
}
-
- protected StrainerException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
-
- }
}
diff --git a/src/Strainer/Exceptions/StrainerFilterNotFoundException.cs b/src/Strainer/Exceptions/StrainerFilterNotFoundException.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a0113f186ee400be4b7280a0600cc51b5660c90a
--- /dev/null
+++ b/src/Strainer/Exceptions/StrainerFilterNotFoundException.cs
@@ -0,0 +1,16 @@
+namespace Fluorite.Strainer.Exceptions;
+
+public class StrainerFilterNotFoundException : StrainerNotFoundException
+{
+ public StrainerFilterNotFoundException(string name) : base(name)
+ {
+ }
+
+ public StrainerFilterNotFoundException(string name, string message) : base(name, message)
+ {
+ }
+
+ public StrainerFilterNotFoundException(string name, string message, Exception innerException) : base(name, message, innerException)
+ {
+ }
+}
diff --git a/src/Strainer/Exceptions/StrainerMethodNotFoundException.cs b/src/Strainer/Exceptions/StrainerMethodNotFoundException.cs
deleted file mode 100644
index 089f006a88d835b7c198616efef9271cd1d4d797..0000000000000000000000000000000000000000
--- a/src/Strainer/Exceptions/StrainerMethodNotFoundException.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-namespace Fluorite.Strainer.Exceptions;
-
-public class StrainerMethodNotFoundException : StrainerException
-{
- public StrainerMethodNotFoundException(string methodName)
- {
- MethodName = Guard.Against.Null(methodName);
- }
-
- public StrainerMethodNotFoundException(string methodName, string message) : base(message)
- {
- MethodName = Guard.Against.Null(methodName);
- }
-
- public StrainerMethodNotFoundException(string methodName, string message, Exception innerException) : base(message, innerException)
- {
- MethodName = Guard.Against.Null(methodName);
- }
-
- public string MethodName { get; }
-}
diff --git a/src/Strainer/Exceptions/StrainerNotFoundException.cs b/src/Strainer/Exceptions/StrainerNotFoundException.cs
new file mode 100644
index 0000000000000000000000000000000000000000..64dc899ec057c1546f12f83b3972ceceb70264a5
--- /dev/null
+++ b/src/Strainer/Exceptions/StrainerNotFoundException.cs
@@ -0,0 +1,21 @@
+namespace Fluorite.Strainer.Exceptions;
+
+public abstract class StrainerNotFoundException : StrainerException
+{
+ protected StrainerNotFoundException(string name)
+ {
+ Name = Guard.Against.Null(name);
+ }
+
+ protected StrainerNotFoundException(string name, string message) : base(message)
+ {
+ Name = Guard.Against.Null(name);
+ }
+
+ protected StrainerNotFoundException(string name, string message, Exception innerException) : base(message, innerException)
+ {
+ Name = Guard.Against.Null(name);
+ }
+
+ public string Name { get; }
+}
diff --git a/src/Strainer/Exceptions/StrainerSortNotFoundException.cs b/src/Strainer/Exceptions/StrainerSortNotFoundException.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1f5c075959e5f637eda780fe5c388c41667e4f6a
--- /dev/null
+++ b/src/Strainer/Exceptions/StrainerSortNotFoundException.cs
@@ -0,0 +1,16 @@
+namespace Fluorite.Strainer.Exceptions;
+
+public class StrainerSortNotFoundException : StrainerNotFoundException
+{
+ public StrainerSortNotFoundException(string name) : base(name)
+ {
+ }
+
+ public StrainerSortNotFoundException(string name, string message) : base(name, message)
+ {
+ }
+
+ public StrainerSortNotFoundException(string name, string message, Exception innerException) : base(name, message, innerException)
+ {
+ }
+}
diff --git a/src/Strainer/Models/Filtering/Operators/FilterExpressionContext.cs b/src/Strainer/Models/Filtering/Operators/FilterExpressionContext.cs
index 76c874e2f7526f58d1aa4197d0150348de83b415..156de9cbe1ced5993fde07b0c6e8a87f910b9586 100644
--- a/src/Strainer/Models/Filtering/Operators/FilterExpressionContext.cs
+++ b/src/Strainer/Models/Filtering/Operators/FilterExpressionContext.cs
@@ -17,21 +17,49 @@ public class FilterExpressionContext : IFilterExpressionContext
///
/// The property access expression.
///
+ ///
+ /// Gets a value indicating whether Strainer should operate in case insensitive mode
+ /// when comparing values.
+ ///
+ ///
+ /// A value indicating whether associated
+ /// is in fact a already materialized collection.
+ ///
+ ///
+ /// Gets a value indicating whether targeted property is string based.
+ ///
///
/// is .
///
///
/// is .
///
- public FilterExpressionContext(Expression filterValue, Expression propertyValue)
+ public FilterExpressionContext(
+ Expression filterValue,
+ Expression propertyValue,
+ bool isCaseInsensitiveForValues,
+ bool isMaterializedQueryable,
+ bool isStringBasedProperty)
{
FilterValue = Guard.Against.Null(filterValue);
PropertyValue = Guard.Against.Null(propertyValue);
+ IsCaseInsensitiveForValues = isCaseInsensitiveForValues;
+ IsMaterializedQueryable = isMaterializedQueryable;
+ IsStringBasedProperty = isStringBasedProperty;
}
///
public Expression FilterValue { get; }
+ ///
+ public bool IsCaseInsensitiveForValues { get; }
+
+ ///
+ public bool IsMaterializedQueryable { get; }
+
+ ///
+ public bool IsStringBasedProperty { get; }
+
///
public Expression PropertyValue { get; }
}
diff --git a/src/Strainer/Models/Filtering/Operators/FilterOperator.cs b/src/Strainer/Models/Filtering/Operators/FilterOperator.cs
index 980ca5c557c8fdcef2b5da78dc2ae0e3f8a7a7c1..7db9fcfa2edd8d3c2813e16bce792a0f147e9683 100644
--- a/src/Strainer/Models/Filtering/Operators/FilterOperator.cs
+++ b/src/Strainer/Models/Filtering/Operators/FilterOperator.cs
@@ -12,18 +12,18 @@ public class FilterOperator : IFilterOperator
///
/// Initializes a new instance of the class.
///
- public FilterOperator(string name, string symbol, Func expression)
+ public FilterOperator(string name, string symbol, Func expressionFunc)
{
Name = Guard.Against.NullOrWhiteSpace(name);
Symbol = Guard.Against.NullOrWhiteSpace(symbol);
- Expression = Guard.Against.Null(expression);
+ ExpressionProvider = Guard.Against.Null(expressionFunc);
}
///
- /// Gets a func providing an
+ /// Gets a func providing an
/// with filter operator applied when supplied a .
///
- public Func Expression { get; }
+ public Func ExpressionProvider { get; }
///
/// Gets or sets a value indicating whether current
@@ -33,7 +33,7 @@ public class FilterOperator : IFilterOperator
///
/// Gets or sets a value indicating whether associated
- /// uses method
+ /// uses method
/// based on a instance like
/// or .
///
diff --git a/src/Strainer/Models/Filtering/Operators/IFilterExpressionContext.cs b/src/Strainer/Models/Filtering/Operators/IFilterExpressionContext.cs
index ae62c8c3388d4b9499e410ac10051a9d4aa6b8e8..2a5b7a28a6458e1d4c4328004ab69c13a796d53b 100644
--- a/src/Strainer/Models/Filtering/Operators/IFilterExpressionContext.cs
+++ b/src/Strainer/Models/Filtering/Operators/IFilterExpressionContext.cs
@@ -12,6 +12,27 @@ public interface IFilterExpressionContext
///
Expression FilterValue { get; }
+ ///
+ /// Gets a value indicating whether Strainer should operate in case insensitive mode
+ /// when comparing values.
+ ///
+ /// Value taken from global .
+ ///
+ public bool IsCaseInsensitiveForValues { get; }
+
+ ///
+ /// Gets a value indicating whether associated
+ /// is in fact an already materialized collection. In such case database
+ /// collation will not work and other provider-specific
+ /// features, such as EF functions.
+ ///
+ bool IsMaterializedQueryable { get; }
+
+ ///
+ /// Gets a value indicating whether targeted property is string based.
+ ///
+ bool IsStringBasedProperty { get; }
+
///
/// Gets the expression for property value access.
///
diff --git a/src/Strainer/Models/Filtering/Operators/IFilterOperator.cs b/src/Strainer/Models/Filtering/Operators/IFilterOperator.cs
index 893603393dd082e0c7cbcff46dc666ebd5e1105e..64a30f13c98d0134f24a1a0a87de63538a5575cb 100644
--- a/src/Strainer/Models/Filtering/Operators/IFilterOperator.cs
+++ b/src/Strainer/Models/Filtering/Operators/IFilterOperator.cs
@@ -8,10 +8,10 @@ namespace Fluorite.Strainer.Models.Filtering.Operators;
public interface IFilterOperator
{
///
- /// Gets a func providing an
+ /// Gets a func providing an
/// with filter operator applied when supplied a .
///
- Func Expression { get; }
+ Func ExpressionProvider { get; }
///
/// Gets a value indicating whether current
@@ -21,7 +21,7 @@ public interface IFilterOperator
///
/// Gets a value indicating whether associated
- /// uses method
+ /// uses method
/// based on a instance like
/// or .
///
diff --git a/src/Strainer/Models/Filtering/Terms/FilterTerm.cs b/src/Strainer/Models/Filtering/Terms/FilterTerm.cs
index 663f467f958fa1657ad56a3ec029791c935f08f1..de586cdf6e7a9daecc9aff722347e294dd915896 100644
--- a/src/Strainer/Models/Filtering/Terms/FilterTerm.cs
+++ b/src/Strainer/Models/Filtering/Terms/FilterTerm.cs
@@ -5,7 +5,7 @@ namespace Fluorite.Strainer.Models.Filtering.Terms;
///
/// Holds segregated details about a single filtering term.
///
-public class FilterTerm : IFilterTerm, IEquatable
+public class FilterTerm : IFilterTerm
{
///
/// Initializes a new instance of the class.
@@ -37,66 +37,4 @@ public class FilterTerm : IFilterTerm, IEquatable
/// Gets or sets the list of values.
///
public IList Values { get; set; }
-
- public static bool operator ==(FilterTerm term1, FilterTerm term2)
- {
- return EqualityComparer.Default.Equals(term1, term2);
- }
-
- public static bool operator !=(FilterTerm term1, FilterTerm term2)
- {
- return !(term1 == term2);
- }
-
- ///
- /// Checks if current instance of
- /// is equal to other instance.
- ///
- ///
- /// Other instance.
- ///
- ///
- /// if provided other
- /// instance is equal to the current one; otherwise .
- ///
- public override bool Equals(object obj)
- {
- return Equals(obj as FilterTerm);
- }
-
- ///
- /// Checks if current instance of
- /// is equal to other instance.
- ///
- ///
- /// Other instance.
- ///
- ///
- /// if provided other
- /// instance is equal to the current one; otherwise .
- ///
- public bool Equals(FilterTerm? other)
- {
- return other is not null &&
- Names.SequenceEqual(other.Names) &&
- EqualityComparer.Default.Equals(Operator, other.Operator) &&
- Values.SequenceEqual(other.Values);
- }
-
- ///
- /// Gets hash code representation of current
- /// .
- ///
- ///
- /// A hash code for the current .
- ///
- public override int GetHashCode()
- {
- var hashCode = 215681951;
- hashCode = (hashCode * -1521134295) + EqualityComparer>.Default.GetHashCode(Names);
- hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Operator);
- hashCode = (hashCode * -1521134295) + EqualityComparer>.Default.GetHashCode(Values);
-
- return hashCode;
- }
}
diff --git a/src/Strainer/Models/Metadata/IObjectMetadata.cs b/src/Strainer/Models/Metadata/IObjectMetadata.cs
index b7b7c0830479370942281d67c10d397dd38749a4..1d71e4946877094a34430bd8889ac52b9cb5c209 100644
--- a/src/Strainer/Models/Metadata/IObjectMetadata.cs
+++ b/src/Strainer/Models/Metadata/IObjectMetadata.cs
@@ -1,4 +1,5 @@
-using System.Reflection;
+using Fluorite.Strainer.Models.Sorting;
+using System.Reflection;
namespace Fluorite.Strainer.Models.Metadata;
@@ -9,15 +10,15 @@ namespace Fluorite.Strainer.Models.Metadata;
public interface IObjectMetadata
{
///
- /// Gets a property name being default sorting property for marked object.
+ /// Gets a property name that will be used as a default (fallback) property
+ /// when no sorting information is available but sorting needs to be applied.
///
string DefaultSortingPropertyName { get; }
///
- /// Gets a value indicating whether default
- /// sorting way for marked object is descending.
+ /// Gets default sorting way used when applying sorting using default sorting property.
///
- bool IsDefaultSortingDescending { get; }
+ SortingWay? DefaultSortingWay { get; }
///
/// Gets a value indicating whether related
diff --git a/src/Strainer/Models/Metadata/IPropertyMetadata.cs b/src/Strainer/Models/Metadata/IPropertyMetadata.cs
index d6e5bf97df1ae792605ba6dc974edd65d9655d33..3508b0f4c877d6407b2753aa69d5dc8438c80553 100644
--- a/src/Strainer/Models/Metadata/IPropertyMetadata.cs
+++ b/src/Strainer/Models/Metadata/IPropertyMetadata.cs
@@ -1,4 +1,5 @@
-using System.Reflection;
+using Fluorite.Strainer.Models.Sorting;
+using System.Reflection;
namespace Fluorite.Strainer.Models.Metadata;
@@ -17,16 +18,16 @@ public interface IPropertyMetadata
/// property should be used as a default (fallback) property when
/// no sorting information was provided but sorting was still requested.
///
- /// Default sorting is not perfomed when sorting information was not
+ /// Default sorting is not perfomed when sorting information is not
/// properly recognized.
///
bool IsDefaultSorting { get; }
///
- /// Gets a value indicating whether default
- /// sorting should be performed in a descending way.
+ /// Gets default sorting way used when related property is marked
+ /// as a default sorting property.
///
- bool IsDefaultSortingDescending { get; }
+ SortingWay? DefaultSortingWay { get; }
///
/// Gets a value indicating whether related
diff --git a/src/Strainer/Models/Metadata/ObjectMetadata.cs b/src/Strainer/Models/Metadata/ObjectMetadata.cs
index 6053cda0dfa1e290c06b6e96afffdab336dae8d5..2c2dd0be21493cc85b8b356f0a06ae1cba9c1a36 100644
--- a/src/Strainer/Models/Metadata/ObjectMetadata.cs
+++ b/src/Strainer/Models/Metadata/ObjectMetadata.cs
@@ -1,4 +1,5 @@
-using System.Reflection;
+using Fluorite.Strainer.Models.Sorting;
+using System.Reflection;
namespace Fluorite.Strainer.Models.Metadata;
@@ -13,25 +14,19 @@ public class ObjectMetadata : IObjectMetadata
///
public ObjectMetadata(
string defaultSortingPropertyName,
- bool isDefaultSortingDescending,
- PropertyInfo defaultSortingPropertyInfo)
+ PropertyInfo defaultSortingPropertyInfo,
+ SortingWay? defaultSortingWay)
{
DefaultSortingPropertyName = Guard.Against.NullOrWhiteSpace(defaultSortingPropertyName);
- IsDefaultSortingDescending = isDefaultSortingDescending;
DefaultSortingPropertyInfo = Guard.Against.Null(defaultSortingPropertyInfo);
+ DefaultSortingWay = defaultSortingWay;
}
- ///
- /// Gets a property name being default sorting property
- /// for marked object.
- ///
+ ///
public string DefaultSortingPropertyName { get; }
- ///
- /// Gets a value indicating whether default
- /// sorting way for marked object is descending.
- ///
- public bool IsDefaultSortingDescending { get; }
+ ///
+ public SortingWay? DefaultSortingWay { get; }
///
/// Gets or sets a value indicating whether related
@@ -45,8 +40,6 @@ public class ObjectMetadata : IObjectMetadata
///
public bool IsSortable { get; set; }
- ///
- /// Gets the for default sorting property.
- ///
+ ///
public PropertyInfo DefaultSortingPropertyInfo { get; }
}
diff --git a/src/Strainer/Models/Metadata/PropertyMetadata.cs b/src/Strainer/Models/Metadata/PropertyMetadata.cs
index 1252435a8bb46d4bf3c57a3af5ebadf636c86c87..10fc2ca25a1378b9fae8507f677dc3faa6c6ed90 100644
--- a/src/Strainer/Models/Metadata/PropertyMetadata.cs
+++ b/src/Strainer/Models/Metadata/PropertyMetadata.cs
@@ -1,4 +1,5 @@
-using System.Diagnostics;
+using Fluorite.Strainer.Models.Sorting;
+using System.Diagnostics;
using System.Reflection;
namespace Fluorite.Strainer.Models.Metadata;
@@ -7,7 +8,7 @@ namespace Fluorite.Strainer.Models.Metadata;
/// Represents default property metadata model.
///
[DebuggerDisplay("\\{" + nameof(Name) + " = " + "{" + nameof(Name) + "} \\}")]
-public class PropertyMetadata : IPropertyMetadata, IEquatable
+public class PropertyMetadata : IPropertyMetadata
{
///
/// Initializes a new instance of the class.
@@ -34,16 +35,16 @@ public class PropertyMetadata : IPropertyMetadata, IEquatable
/// property should be used as a default (fallback) property when
/// no sorting information was provided but sorting was still requested.
///
- /// Default sorting is not perfomed when sorting information was not
+ /// Default sorting is not perfomed when sorting information is not
/// properly recognized.
///
public bool IsDefaultSorting { get; set; }
///
- /// Gets or sets a value indicating whether default
- /// sorting should be performed in a descending way.
+ /// Gets or sets default sorting way used when related property is marked
+ /// as a default sorting property.
///
- public bool IsDefaultSortingDescending { get; set; }
+ public SortingWay? DefaultSortingWay { get; set; }
///
/// Gets or sets a value indicating whether related
@@ -57,83 +58,9 @@ public class PropertyMetadata : IPropertyMetadata, IEquatable
///
public bool IsSortable { get; set; }
- ///
- /// Gets the name under which property was marked.
- ///
+ ///
public string Name { get; }
- ///
- /// Gets the for related
- /// property.
- ///
+ ///
public PropertyInfo PropertyInfo { get; }
-
- public static bool operator ==(PropertyMetadata metadata1, PropertyMetadata metadata2)
- {
- return EqualityComparer.Default.Equals(metadata1, metadata2);
- }
-
- public static bool operator !=(PropertyMetadata metadata1, PropertyMetadata metadata2)
- {
- return !(metadata1 == metadata2);
- }
-
- ///
- /// Checks if current instance of
- /// is equal to other instance.
- ///
- ///
- /// Other instance.
- ///
- ///
- /// if provided other
- /// instance is equal to the current one; otherwise .
- ///
- public override bool Equals(object obj)
- {
- return Equals(obj as PropertyMetadata);
- }
-
- ///
- /// Checks if current instance of
- /// is equal to other instance.
- ///
- ///
- /// Other instance.
- ///
- ///
- /// if provided other
- /// instance is equal to the current one; otherwise .
- ///
- public bool Equals(PropertyMetadata? other)
- {
- return other is not null &&
- DisplayName == other.DisplayName &&
- IsDefaultSorting == other.IsDefaultSorting &&
- IsDefaultSortingDescending == other.IsDefaultSortingDescending &&
- IsFilterable == other.IsFilterable &&
- IsSortable == other.IsSortable &&
- Name == other.Name &&
- EqualityComparer.Default.Equals(PropertyInfo, other.PropertyInfo);
- }
-
- ///
- /// Gets hash code representation of current
- /// .
- ///
- ///
- /// A hash code for the current .
- ///
- public override int GetHashCode()
- {
- var hashCode = -1500598692;
- hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(DisplayName);
- hashCode = (hashCode * -1521134295) + IsDefaultSorting.GetHashCode();
- hashCode = (hashCode * -1521134295) + IsDefaultSortingDescending.GetHashCode();
- hashCode = (hashCode * -1521134295) + IsFilterable.GetHashCode();
- hashCode = (hashCode * -1521134295) + IsSortable.GetHashCode();
- hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Name);
- hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(PropertyInfo);
- return hashCode;
- }
}
diff --git a/src/Strainer/Models/Sorting/SortingWay.cs b/src/Strainer/Models/Sorting/SortingWay.cs
index 04d8ce2de547163e58f8e60ab78f3859bd62cc5f..4671300d4463946917fc0155dd99282d2b63e64f 100644
--- a/src/Strainer/Models/Sorting/SortingWay.cs
+++ b/src/Strainer/Models/Sorting/SortingWay.cs
@@ -5,15 +5,10 @@
///
public enum SortingWay
{
- ///
- /// Unknown sorting way, that could not be established.
- ///
- Unknown = 0,
-
///
/// Ascending sorting way.
///
- Ascending,
+ Ascending = 1,
///
/// Descending sorting way.
diff --git a/src/Strainer/Models/Sorting/Terms/SortTerm.cs b/src/Strainer/Models/Sorting/Terms/SortTerm.cs
index 20b74439b19fb29a2938310ba17744d9519a276a..2a562f64266301c14c2181bc3d244d9d27733c44 100644
--- a/src/Strainer/Models/Sorting/Terms/SortTerm.cs
+++ b/src/Strainer/Models/Sorting/Terms/SortTerm.cs
@@ -8,7 +8,7 @@ namespace Fluorite.Strainer.Models.Sorting.Terms;
[DebuggerDisplay("\\{" +
nameof(Name) + " = " + "{" + nameof(Name) + "}, " +
nameof(IsDescending) + " = " + "{" + nameof(IsDescending) + "}" + "\\}")]
-public class SortTerm : ISortTerm, IEquatable
+public class SortTerm : ISortTerm
{
///
/// Initializes a new instance of the class.
@@ -36,63 +36,4 @@ public class SortTerm : ISortTerm, IEquatable
/// Gets the name within sorting term.
///
public string Name { get; }
-
- public static bool operator ==(SortTerm term1, SortTerm term2)
- {
- return EqualityComparer.Default.Equals(term1, term2);
- }
-
- public static bool operator !=(SortTerm term1, SortTerm term2)
- {
- return !(term1 == term2);
- }
-
- ///
- /// Checks if current instance of
- /// is equal to other instance.
- ///
- ///
- /// Other instance.
- ///
- ///
- /// if provided other
- /// instance is equal to the current one; otherwise .
- ///
- public override bool Equals(object obj)
- {
- return Equals(obj as SortTerm);
- }
-
- ///
- /// Checks if current instance of is equal
- /// to other instance.
- ///
- ///
- /// Other instance.
- ///
- ///
- /// if provided other
- /// instance is equal to the current one; otherwise .
- ///
- public bool Equals(SortTerm? other)
- {
- return other is not null &&
- IsDescending == other.IsDescending &&
- Name == other.Name;
- }
-
- ///
- /// Gets hash code representation of current
- /// .
- ///
- ///
- /// A hash code for the current .
- ///
- public override int GetHashCode()
- {
- var hashCode = 1436560617;
- hashCode = (hashCode * -1521134295) + IsDescending.GetHashCode();
- hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Name);
- return hashCode;
- }
}
diff --git a/src/Strainer/Models/StrainerOptions.cs b/src/Strainer/Models/StrainerOptions.cs
index 6b6c85a517a2ecf82bfc373429709f0339221fe6..a67d7b2b4e825be2247029f3372fdd54b4e92290 100644
--- a/src/Strainer/Models/StrainerOptions.cs
+++ b/src/Strainer/Models/StrainerOptions.cs
@@ -40,7 +40,7 @@ public class StrainerOptions
///
/// Gets or sets a value indicating whether
- /// Strainer should operatre in case insensitive mode when comparing values.
+ /// Strainer should operate in case insensitive mode when comparing values.
///
/// This for example affects the way of comparing value of incoming filter
/// with actual property value.
diff --git a/src/Strainer/Services/Configuration/GenericModuleLoadingStrategy.cs b/src/Strainer/Services/Configuration/GenericModuleLoadingStrategy.cs
index 644d8e1b1eace82038bdbe4a11b5a775230f6725..ccb474634e1c53fc208cf9d001ea1c5f417cfda6 100644
--- a/src/Strainer/Services/Configuration/GenericModuleLoadingStrategy.cs
+++ b/src/Strainer/Services/Configuration/GenericModuleLoadingStrategy.cs
@@ -19,6 +19,11 @@ public class GenericModuleLoadingStrategy : IGenericModuleLoadingStrategy, IModu
.GetType()
.GetInterfaces()
.FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IStrainerModule<>));
+ if (genericStrainerModuleInterfaceType is null)
+ {
+ throw new ArgumentException("Strainer module must be generic.", nameof(strainerModule));
+ }
+
var moduleTypeParameter = genericStrainerModuleInterfaceType.GetGenericArguments().First();
var builder = _strainerModuleBuilderFactory.Create(moduleTypeParameter, strainerModule);
var method = genericStrainerModuleInterfaceType.GetMethod(nameof(IStrainerModule