mirror of https://github.com/sean-m/McRule.git
Added solution file and updated filter extensions
parent
f193376a6d
commit
dbed12ddc9
|
@ -0,0 +1,13 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider ignored files
|
||||
/modules.xml
|
||||
/.idea.Ruler.iml
|
||||
/contentModel.xml
|
||||
/projectSettingsUpdater.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ruler", "Ruler\Ruler.csproj", "{E4B8E05A-80A5-4F0D-A3DA-BB6AA377153D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RulerDev", "RulerDev\RulerDev.csproj", "{0E6DF52C-D171-4E84-8D6D-BB580DF35E51}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E4B8E05A-80A5-4F0D-A3DA-BB6AA377153D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E4B8E05A-80A5-4F0D-A3DA-BB6AA377153D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E4B8E05A-80A5-4F0D-A3DA-BB6AA377153D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E4B8E05A-80A5-4F0D-A3DA-BB6AA377153D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0E6DF52C-D171-4E84-8D6D-BB580DF35E51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0E6DF52C-D171-4E84-8D6D-BB580DF35E51}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0E6DF52C-D171-4E84-8D6D-BB580DF35E51}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0E6DF52C-D171-4E84-8D6D-BB580DF35E51}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
149
Ruler/Ruler.cs
149
Ruler/Ruler.cs
|
@ -59,71 +59,114 @@ public static class PredicateBuilder
|
|||
|
||||
|
||||
public static class FilterPolicyExtensions
|
||||
{
|
||||
public enum RuleOperator {
|
||||
And,
|
||||
Or
|
||||
}
|
||||
{
|
||||
public enum RuleOperator {
|
||||
And,
|
||||
Or
|
||||
}
|
||||
|
||||
// Dynamicall build an expression suitable for filtering in a Where clause
|
||||
public static Expression<Func<T, bool>> GetFilterForType<T>(string property, string value)
|
||||
{
|
||||
var parameter = Expression.Parameter(typeof(T), "x");
|
||||
var opLeft = Expression.Property(parameter, property);
|
||||
public static Expression<Func<T, bool>> AddFilterToStringProperty<T>(
|
||||
Expression<Func<T, string>> expression, string filter, string filterType)
|
||||
{
|
||||
|
||||
var opRight = Expression.Constant(value);
|
||||
var comparison = Expression.Equal(opLeft, opRight);
|
||||
#if DEBUG
|
||||
if (!(filterType == "StartsWith" || filterType == "EndsWith" || filterType == "Contains"))
|
||||
{
|
||||
throw new Exception($"filterType must equal StartsWith, EndsWith or Contains. Passed {filterType}");
|
||||
}
|
||||
|
||||
return Expression.Lambda<Func<T, bool>>(comparison, parameter);
|
||||
}
|
||||
#endif
|
||||
// Check that the property isn't null, otherwise we'd hit null object exceptions at runtime
|
||||
var notNull = Expression.NotEqual(expression.Body,Expression.Constant(null));
|
||||
|
||||
// Setup calls to EtartsWith, EndsWith, or Contains
|
||||
// TODO expressionArgs was used to pass multiple values for case insensitive compare, wasn't
|
||||
// mapping the method correctly when used with EF so need to revisit that
|
||||
var expressionArgs = new Expression[] {Expression.Constant(filter)};
|
||||
var strPredicate = Expression.Call(expression.Body, filterType, null, expressionArgs);
|
||||
|
||||
// Combine a list of expressions inclusively
|
||||
public static Expression<Func<T, bool>> CombineAnd<T>(IEnumerable<Expression<Func<T, bool>>> predicates)
|
||||
{
|
||||
if (predicates.Count() == 0) return null;
|
||||
var filterExpression = Expression.AndAlso(notNull, strPredicate);
|
||||
|
||||
var final = predicates.First();
|
||||
foreach (var next in predicates.Skip(1))
|
||||
final = PredicateBuilder.And(final, next);
|
||||
|
||||
return final;
|
||||
}
|
||||
return Expression.Lambda<Func<T, bool>>(
|
||||
filterExpression,
|
||||
expression.Parameters);
|
||||
}
|
||||
|
||||
// Dynamically build an expression suitable for filtering in a Where clause
|
||||
public static Expression<Func<T, bool>> GetFilterForType<T>(string property, string value)
|
||||
{
|
||||
var parameter = Expression.Parameter(typeof(T), "x");
|
||||
var opLeft = Expression.Property(parameter, property);
|
||||
var opRight = Expression.Constant(value);
|
||||
var comparison = Expression.Equal(opLeft, opRight);
|
||||
|
||||
// For string comparisons using wildcards, trim the wildcard characters and pass to the comparison method
|
||||
if (opLeft.Type == typeof(string)) {
|
||||
// Grab the object property for use in the inner expression body
|
||||
var strParam = Expression.Lambda<Func<T,string>>(opLeft, parameter);
|
||||
|
||||
if (value.StartsWith("*") && value.EndsWith("*")) {
|
||||
return AddFilterToStringProperty<T>(strParam, value.Trim('*'), "Contains");
|
||||
} else if (value.StartsWith("*")) {
|
||||
return AddFilterToStringProperty<T>(strParam, value.TrimStart('*'), "EndsWith");
|
||||
} else if (value.EndsWith("*")) {
|
||||
return AddFilterToStringProperty<T>(strParam, value.TrimEnd('*'), "StartsWith");
|
||||
} else {
|
||||
return Expression.Lambda<Func<T, bool>>(comparison, parameter);
|
||||
}
|
||||
}
|
||||
|
||||
return Expression.Lambda<Func<T, bool>>(comparison, parameter);
|
||||
}
|
||||
|
||||
// Combine a list of expressions inclusively
|
||||
public static Expression<Func<T, bool>>? CombineAnd<T>(IEnumerable<Expression<Func<T, bool>>> predicates)
|
||||
{
|
||||
if (predicates.Count() == 0) return null;
|
||||
|
||||
var final = predicates.First();
|
||||
foreach (var next in predicates.Skip(1))
|
||||
final = PredicateBuilder.And(final, next);
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
|
||||
// Combine a list of expressions inclusively
|
||||
public static Expression<Func<T, bool>> CombineOr<T>(IEnumerable<Expression<Func<T, bool>>> predicates)
|
||||
{
|
||||
if (predicates.Count() == 0) return null;
|
||||
// Combine a list of expressions inclusively
|
||||
public static Expression<Func<T, bool>>? CombineOr<T>(IEnumerable<Expression<Func<T, bool>>> predicates)
|
||||
{
|
||||
if (predicates.Count() == 0) return null;
|
||||
|
||||
var final = predicates.First();
|
||||
foreach (var next in predicates.Skip(1))
|
||||
final = PredicateBuilder.Or(final, next);
|
||||
var final = predicates.First();
|
||||
foreach (var next in predicates.Skip(1))
|
||||
final = PredicateBuilder.Or(final, next);
|
||||
|
||||
return final;
|
||||
}
|
||||
return final;
|
||||
}
|
||||
|
||||
|
||||
// Combine a list of expressions inclusively
|
||||
public static Expression<Func<T, bool>> CombinePredicates<T>(IEnumerable<Expression<Func<T, bool>>> predicates, FilterPolicyExtensions.RuleOperator op)
|
||||
{
|
||||
if (predicates.Count() == 0) return null;
|
||||
// Combine a list of expressions inclusively
|
||||
public static Expression<Func<T, bool>>? CombinePredicates<T>(IEnumerable<Expression<Func<T, bool>>> predicates,
|
||||
FilterPolicyExtensions.RuleOperator op)
|
||||
{
|
||||
if (predicates.Count() == 0) return null;
|
||||
|
||||
if (op == RuleOperator.And)
|
||||
{
|
||||
return CombineAnd(predicates);
|
||||
}
|
||||
return CombineOr(predicates);
|
||||
}
|
||||
if (op == RuleOperator.And)
|
||||
{
|
||||
return CombineAnd(predicates);
|
||||
}
|
||||
return CombineOr(predicates);
|
||||
}
|
||||
|
||||
|
||||
public static Expression<Func<T, bool>> GetFilterExpression<T>(this FilterPolicy policy)
|
||||
{
|
||||
var predicates = new List<Expression<Func<T, bool>>>();
|
||||
foreach (var constraints in policy.scope)
|
||||
{
|
||||
predicates.Add(GetFilterForType<T>(constraints.Item1, constraints.Item2));
|
||||
}
|
||||
|
||||
return CombinePredicates<T>(predicates, policy.ruleOperator);
|
||||
}
|
||||
public static Expression<Func<T, bool>>? GetFilterExpression<T>(this FilterPolicy policy)
|
||||
{
|
||||
var predicates = new List<Expression<Func<T, bool>>>();
|
||||
foreach (var constraints in policy.scope)
|
||||
{
|
||||
predicates.Add(GetFilterForType<T>(constraints.Item1, constraints.Item2));
|
||||
}
|
||||
|
||||
return CombinePredicates<T>(predicates, policy.ruleOperator);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ruler\Ruler.csproj" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ruler\Ruler.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"sdk": {
|
||||
"version": "6.0.0",
|
||||
"rollForward": "latestMajor",
|
||||
"allowPrerelease": false
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue