@@ -30,6 +30,8 @@ public abstract class ComparisonOperator : SmartEnum<ComparisonOperator>
3030 public static ComparisonOperator CaseSensitiveHasCountLessThanOperator = new HasCountLessThanType ( ) ;
3131 public static ComparisonOperator CaseSensitiveHasCountGreaterThanOrEqualOperator = new HasCountGreaterThanOrEqualType ( ) ;
3232 public static ComparisonOperator CaseSensitiveHasCountLessThanOrEqualOperator = new HasCountLessThanOrEqualType ( ) ;
33+ public static ComparisonOperator CaseSensitiveHasOperator = new HasType ( ) ;
34+ public static ComparisonOperator CaseSensitiveDoesNotHaveOperator = new DoesNotHaveType ( ) ;
3335
3436 public static ComparisonOperator EqualsOperator ( bool caseInsensitive = false , bool usesAll = false ) => new EqualsType ( caseInsensitive ) ;
3537 public static ComparisonOperator NotEqualsOperator ( bool caseInsensitive = false , bool usesAll = false ) => new NotEqualsType ( caseInsensitive ) ;
@@ -52,6 +54,8 @@ public abstract class ComparisonOperator : SmartEnum<ComparisonOperator>
5254 public static ComparisonOperator HasCountLessThanOperator ( bool caseInsensitive = false , bool usesAll = false ) => new HasCountLessThanType ( caseInsensitive ) ;
5355 public static ComparisonOperator HasCountGreaterThanOrEqualOperator ( bool caseInsensitive = false , bool usesAll = false ) => new HasCountGreaterThanOrEqualType ( caseInsensitive ) ;
5456 public static ComparisonOperator HasCountLessThanOrEqualOperator ( bool caseInsensitive = false , bool usesAll = false ) => new HasCountLessThanOrEqualType ( caseInsensitive ) ;
57+ public static ComparisonOperator HasOperator ( bool caseInsensitive = false , bool usesAll = false ) => new HasType ( caseInsensitive ) ;
58+ public static ComparisonOperator DoesNotHaveOperator ( bool caseInsensitive = false , bool usesAll = false ) => new DoesNotHaveType ( caseInsensitive ) ;
5559
5660
5761 public static ComparisonOperator GetByOperatorString ( string op , bool caseInsensitive = false , bool usesAll = false )
@@ -148,6 +152,14 @@ public static ComparisonOperator GetByOperatorString(string op, bool caseInsensi
148152 {
149153 newOperator = new HasCountLessThanOrEqualType ( caseInsensitive , usesAll ) ;
150154 }
155+ if ( comparisonOperator is HasType )
156+ {
157+ newOperator = new HasType ( caseInsensitive , usesAll ) ;
158+ }
159+ if ( comparisonOperator is DoesNotHaveType )
160+ {
161+ newOperator = new DoesNotHaveType ( caseInsensitive , usesAll ) ;
162+ }
151163
152164 return newOperator == null
153165 ? throw new Exception ( $ "Operator { op } is not supported")
@@ -628,6 +640,49 @@ public override Expression GetExpression<T>(Expression left, Expression right, T
628640 }
629641 }
630642
643+ private class HasType : ComparisonOperator
644+ {
645+ public HasType ( bool caseInsensitive = false , bool usesAll = false ) : base ( "^$" , 21 , caseInsensitive , usesAll )
646+ {
647+ }
648+
649+ public override string Operator ( ) => CaseInsensitive ? $ "{ Name } { CaseSensitiveAppendix } " : Name ;
650+ public override Expression GetExpression < T > ( Expression left , Expression right , Type ? dbContextType )
651+ {
652+ if ( left . Type . IsGenericType &&
653+ ( left . Type . GetGenericTypeDefinition ( ) == typeof ( List < > ) ||
654+ left . Type . GetGenericTypeDefinition ( ) == typeof ( ICollection < > ) ||
655+ left . Type . GetGenericTypeDefinition ( ) == typeof ( IList < > ) ||
656+ typeof ( IEnumerable < > ) . IsAssignableFrom ( left . Type . GetGenericTypeDefinition ( ) ) ) )
657+ {
658+ return GetCollectionExpression ( left , right , Expression . Equal , UsesAll ) ;
659+ }
660+
661+ throw new Exception ( "DoesNotHaveType is only supported for collections" ) ;
662+ }
663+ }
664+
665+ private class DoesNotHaveType : ComparisonOperator
666+ {
667+ public DoesNotHaveType ( bool caseInsensitive = false , bool usesAll = false ) : base ( "!^$" , 22 , caseInsensitive , usesAll )
668+ {
669+ }
670+
671+ public override string Operator ( ) => CaseInsensitive ? $ "{ Name } { CaseSensitiveAppendix } " : Name ;
672+ public override Expression GetExpression < T > ( Expression left , Expression right , Type ? dbContextType )
673+ {
674+ if ( left . Type . IsGenericType &&
675+ ( left . Type . GetGenericTypeDefinition ( ) == typeof ( List < > ) ||
676+ left . Type . GetGenericTypeDefinition ( ) == typeof ( ICollection < > ) ||
677+ left . Type . GetGenericTypeDefinition ( ) == typeof ( IList < > ) ||
678+ typeof ( IEnumerable < > ) . IsAssignableFrom ( left . Type . GetGenericTypeDefinition ( ) ) ) )
679+ {
680+ return GetCollectionExpression ( left , right , Expression . NotEqual , UsesAll ) ;
681+ }
682+
683+ throw new Exception ( "DoesNotHaveType is only supported for collections" ) ;
684+ }
685+ }
631686
632687 internal class ComparisonAliasMatch
633688 {
@@ -734,6 +789,16 @@ internal static List<ComparisonAliasMatch> GetAliasMatches(IQueryKitConfiguratio
734789 matches . Add ( new ComparisonAliasMatch { Alias = aliases . HasCountLessThanOrEqualOperator , Operator = HasCountLessThanOrEqualOperator ( ) . Operator ( ) } ) ;
735790 matches . Add ( new ComparisonAliasMatch { Alias = $ "{ aliases . HasCountLessThanOrEqualOperator } { caseInsensitiveAppendix } ", Operator = $ "{ HasCountLessThanOrEqualOperator ( true ) . Operator ( ) } " } ) ;
736791 }
792+ if ( aliases . HasOperator != HasOperator ( ) . Operator ( ) )
793+ {
794+ matches . Add ( new ComparisonAliasMatch { Alias = aliases . HasOperator , Operator = HasOperator ( ) . Operator ( ) } ) ;
795+ matches . Add ( new ComparisonAliasMatch { Alias = $ "{ aliases . HasOperator } { caseInsensitiveAppendix } ", Operator = $ "{ HasOperator ( true ) . Operator ( ) } " } ) ;
796+ }
797+ if ( aliases . DoesNotHaveOperator != DoesNotHaveOperator ( ) . Operator ( ) )
798+ {
799+ matches . Add ( new ComparisonAliasMatch { Alias = aliases . DoesNotHaveOperator , Operator = DoesNotHaveOperator ( ) . Operator ( ) } ) ;
800+ matches . Add ( new ComparisonAliasMatch { Alias = $ "{ aliases . DoesNotHaveOperator } { caseInsensitiveAppendix } ", Operator = $ "{ DoesNotHaveOperator ( true ) . Operator ( ) } " } ) ;
801+ }
737802
738803 return matches ;
739804 }
@@ -792,7 +857,7 @@ private Expression GetCollectionExpression(Expression left, Expression right, st
792857 : Expression . Call ( anyMethod , left , anyLambda ) ;
793858 }
794859
795- public Expression GetCountExpression ( Expression left , Expression right , string methodName )
860+ private Expression GetCountExpression ( Expression left , Expression right , string methodName )
796861 {
797862 var leftAsEnumerableType = left . Type . GetInterface ( nameof ( IEnumerable ) ) ;
798863 if ( leftAsEnumerableType == null )
0 commit comments