Skip to content

Commit be03178

Browse files
committed
Merge branch 'dev'
2 parents 18c9bcf + c5c4fbf commit be03178

File tree

5 files changed

+266
-13
lines changed

5 files changed

+266
-13
lines changed

common.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
3-
<Version>4.8.0</Version>
3+
<Version>4.9.0</Version>
44
<NoWarn>$(NoWarn);CS1591</NoWarn>
55
<PackageIconUrl>http://www.aspnetboilerplate.com/images/abp_nupkg.png</PackageIconUrl>
66
<PackageProjectUrl>http://www.aspnetboilerplate.com/</PackageProjectUrl>

src/Abp.Zero.Common/Notifications/NotificationStore.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ public virtual async Task DeleteAllUserNotificationsAsync(UserIdentifier user, U
211211

212212
private Expression<Func<UserNotificationInfo, bool>> CreateNotificationFilterPredicate(UserIdentifier user, UserNotificationState? state = null, DateTime? startDate = null, DateTime? endDate = null)
213213
{
214-
var predicate = PredicateBuilder.True<UserNotificationInfo>();
214+
var predicate = PredicateBuilder.New<UserNotificationInfo>();
215215
predicate = predicate.And(p => p.UserId == user.UserId);
216216

217217
if (startDate.HasValue)
Lines changed: 235 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,253 @@
11
using System;
2-
using System.Linq;
2+
using System.Collections.ObjectModel;
33
using System.Linq.Expressions;
4+
using JetBrains.Annotations;
45

56
namespace Abp.Linq.Expressions
67
{
8+
// Codes below are taken from https://github.com/scottksmith95/LINQKit project.
9+
10+
/// <summary> The Predicate Operator </summary>
11+
internal enum PredicateOperator
12+
{
13+
/// <summary> The "Or" </summary>
14+
Or,
15+
16+
/// <summary> The "And" </summary>
17+
And
18+
}
19+
20+
/// <summary>
21+
/// See http://www.albahari.com/expressions for information and examples.
22+
/// </summary>
723
internal static class PredicateBuilder
824
{
9-
public static Expression<Func<T, bool>> True<T>() { return f => true; }
25+
private class RebindParameterVisitor : ExpressionVisitor
26+
{
27+
private readonly ParameterExpression _oldParameter;
28+
private readonly ParameterExpression _newParameter;
29+
30+
public RebindParameterVisitor(ParameterExpression oldParameter, ParameterExpression newParameter)
31+
{
32+
_oldParameter = oldParameter;
33+
_newParameter = newParameter;
34+
}
35+
36+
protected override Expression VisitParameter(ParameterExpression node)
37+
{
38+
if (node == _oldParameter)
39+
{
40+
return _newParameter;
41+
}
42+
43+
return base.VisitParameter(node);
44+
}
45+
}
46+
47+
/// <summary> Start an expression </summary>
48+
public static ExpressionStarter<T> New<T>(Expression<Func<T, bool>> expr = null) { return new ExpressionStarter<T>(expr); }
49+
50+
/// <summary> Create an expression with a stub expression true or false to use when the expression is not yet started. </summary>
51+
public static ExpressionStarter<T> New<T>(bool defaultExpression) { return new ExpressionStarter<T>(defaultExpression); }
52+
53+
/// <summary> Always true </summary>
54+
[Obsolete("Use PredicateBuilder.New() instead.")]
55+
public static Expression<Func<T, bool>> True<T>() { return new ExpressionStarter<T>(true); }
56+
57+
/// <summary> Always false </summary>
58+
[Obsolete("Use PredicateBuilder.New() instead.")]
59+
public static Expression<Func<T, bool>> False<T>() { return new ExpressionStarter<T>(false); }
60+
61+
/// <summary> OR </summary>
62+
public static Expression<Func<T, bool>> Or<T>([NotNull] this Expression<Func<T, bool>> expr1, [NotNull] Expression<Func<T, bool>> expr2)
63+
{
64+
var expr2Body = new RebindParameterVisitor(expr2.Parameters[0], expr1.Parameters[0]).Visit(expr2.Body);
65+
return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, expr2Body), expr1.Parameters);
66+
}
67+
68+
/// <summary> AND </summary>
69+
public static Expression<Func<T, bool>> And<T>([NotNull] this Expression<Func<T, bool>> expr1, [NotNull] Expression<Func<T, bool>> expr2)
70+
{
71+
var expr2Body = new RebindParameterVisitor(expr2.Parameters[0], expr1.Parameters[0]).Visit(expr2.Body);
72+
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, expr2Body), expr1.Parameters);
73+
}
74+
75+
/// <summary>
76+
/// Extends the specified source Predicate with another Predicate and the specified PredicateOperator.
77+
/// </summary>
78+
/// <typeparam name="T">The type</typeparam>
79+
/// <param name="first">The source Predicate.</param>
80+
/// <param name="second">The second Predicate.</param>
81+
/// <param name="operator">The Operator (can be "And" or "Or").</param>
82+
/// <returns>Expression{Func{T, bool}}</returns>
83+
public static Expression<Func<T, bool>> Extend<T>([NotNull] this Expression<Func<T, bool>> first, [NotNull] Expression<Func<T, bool>> second, PredicateOperator @operator = PredicateOperator.Or)
84+
{
85+
return @operator == PredicateOperator.Or ? first.Or(second) : first.And(second);
86+
}
87+
88+
/// <summary>
89+
/// Extends the specified source Predicate with another Predicate and the specified PredicateOperator.
90+
/// </summary>
91+
/// <typeparam name="T">The type</typeparam>
92+
/// <param name="first">The source Predicate.</param>
93+
/// <param name="second">The second Predicate.</param>
94+
/// <param name="operator">The Operator (can be "And" or "Or").</param>
95+
/// <returns>Expression{Func{T, bool}}</returns>
96+
public static Expression<Func<T, bool>> Extend<T>([NotNull] this ExpressionStarter<T> first, [NotNull] Expression<Func<T, bool>> second, PredicateOperator @operator = PredicateOperator.Or)
97+
{
98+
return @operator == PredicateOperator.Or ? first.Or(second) : first.And(second);
99+
}
100+
}
101+
102+
/// <summary>
103+
/// ExpressionStarter{T} which eliminates the default 1=0 or 1=1 stub expressions
104+
/// </summary>
105+
/// <typeparam name="T">The type</typeparam>
106+
public class ExpressionStarter<T>
107+
{
108+
internal ExpressionStarter() : this(false) { }
109+
110+
internal ExpressionStarter(bool defaultExpression)
111+
{
112+
if (defaultExpression)
113+
DefaultExpression = f => true;
114+
else
115+
DefaultExpression = f => false;
116+
}
117+
118+
internal ExpressionStarter(Expression<Func<T, bool>> exp) : this(false)
119+
{
120+
_predicate = exp;
121+
}
10122

11-
public static Expression<Func<T, bool>> False<T>() { return f => false; }
123+
/// <summary>The actual Predicate. It can only be set by calling Start.</summary>
124+
private Expression<Func<T, bool>> Predicate => (IsStarted || !UseDefaultExpression) ? _predicate : DefaultExpression;
12125

13-
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
126+
private Expression<Func<T, bool>> _predicate;
127+
128+
/// <summary>Determines if the predicate is started.</summary>
129+
public bool IsStarted => _predicate != null;
130+
131+
/// <summary> A default expression to use only when the expression is null </summary>
132+
public bool UseDefaultExpression => DefaultExpression != null;
133+
134+
/// <summary>The default expression</summary>
135+
public Expression<Func<T, bool>> DefaultExpression { get; set; }
136+
137+
/// <summary>Set the Expression predicate</summary>
138+
/// <param name="exp">The first expression</param>
139+
public Expression<Func<T, bool>> Start(Expression<Func<T, bool>> exp)
140+
{
141+
if (IsStarted)
142+
throw new Exception("Predicate cannot be started again.");
143+
144+
return _predicate = exp;
145+
}
146+
147+
/// <summary>Or</summary>
148+
public Expression<Func<T, bool>> Or([NotNull] Expression<Func<T, bool>> expr2)
149+
{
150+
return (IsStarted) ? _predicate = Predicate.Or(expr2) : Start(expr2);
151+
}
152+
153+
/// <summary>And</summary>
154+
public Expression<Func<T, bool>> And([NotNull] Expression<Func<T, bool>> expr2)
14155
{
15-
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
156+
return (IsStarted) ? _predicate = Predicate.And(expr2) : Start(expr2);
157+
}
16158

17-
return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
159+
/// <summary> Show predicate string </summary>
160+
public override string ToString()
161+
{
162+
return Predicate == null ? null : Predicate.ToString();
18163
}
19164

20-
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
165+
#region Implicit Operators
166+
/// <summary>
167+
/// Allows this object to be implicitely converted to an Expression{Func{T, bool}}.
168+
/// </summary>
169+
/// <param name="right"></param>
170+
public static implicit operator Expression<Func<T, bool>>(ExpressionStarter<T> right)
21171
{
22-
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
172+
return right == null ? null : right.Predicate;
173+
}
23174

24-
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
175+
/// <summary>
176+
/// Allows this object to be implicitely converted to an Expression{Func{T, bool}}.
177+
/// </summary>
178+
/// <param name="right"></param>
179+
public static implicit operator Func<T, bool>(ExpressionStarter<T> right)
180+
{
181+
return right == null ? null : (right.IsStarted || right.UseDefaultExpression) ? right.Predicate.Compile() : null;
182+
}
183+
184+
/// <summary>
185+
/// Allows this object to be implicitely converted to an Expression{Func{T, bool}}.
186+
/// </summary>
187+
/// <param name="right"></param>
188+
public static implicit operator ExpressionStarter<T>(Expression<Func<T, bool>> right)
189+
{
190+
return right == null ? null : new ExpressionStarter<T>(right);
25191
}
192+
#endregion
193+
194+
#region Implement Expression<TDelagate> methods and properties
195+
#if !(NET35)
196+
197+
/// <summary></summary>
198+
public Func<T, bool> Compile() { return Predicate.Compile(); }
199+
#endif
200+
201+
#if !(NET35 || WINDOWS_APP || NETSTANDARD || PORTABLE || PORTABLE40 || UAP)
202+
/// <summary></summary>
203+
public Func<T, bool> Compile(DebugInfoGenerator debugInfoGenerator) { return Predicate.Compile(debugInfoGenerator); }
204+
205+
/// <summary></summary>
206+
public Expression<Func<T, bool>> Update(Expression body, IEnumerable<ParameterExpression> parameters) { return Predicate.Update(body, parameters); }
207+
#endif
208+
#endregion
209+
210+
#region Implement LamdaExpression methods and properties
211+
212+
/// <summary></summary>
213+
public Expression Body => Predicate.Body;
214+
215+
216+
/// <summary></summary>
217+
public ExpressionType NodeType => Predicate.NodeType;
218+
219+
/// <summary></summary>
220+
public ReadOnlyCollection<ParameterExpression> Parameters => Predicate.Parameters;
221+
222+
/// <summary></summary>
223+
public Type Type => Predicate.Type;
224+
225+
#if !(NET35)
226+
/// <summary></summary>
227+
public string Name => Predicate.Name;
228+
229+
/// <summary></summary>
230+
public Type ReturnType => Predicate.ReturnType;
231+
232+
/// <summary></summary>
233+
public bool TailCall => Predicate.TailCall;
234+
#endif
235+
236+
#if !(NET35 || WINDOWS_APP || NETSTANDARD || PORTABLE || PORTABLE40 || UAP)
237+
/// <summary></summary>
238+
public void CompileToMethod(MethodBuilder method) { Predicate.CompileToMethod(method); }
239+
240+
/// <summary></summary>
241+
public void CompileToMethod(MethodBuilder method, DebugInfoGenerator debugInfoGenerator) { Predicate.CompileToMethod(method, debugInfoGenerator); }
242+
243+
#endif
244+
#endregion
245+
246+
#region Implement Expression methods and properties
247+
#if !(NET35)
248+
/// <summary></summary>
249+
public virtual bool CanReduce => Predicate.CanReduce;
250+
#endif
251+
#endregion
26252
}
27253
}

test/Abp.Tests/Linq/Expressions/PredicateBuilder_Tests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public class PredicateBuilder_Tests
1010
public void Test1()
1111
{
1212
var args = new TestArgs();
13-
var predicate = PredicateBuilder.True<TestObj>();
13+
var predicate = PredicateBuilder.New<TestObj>();
1414

1515
predicate = predicate.And(t => args.Value == t.Value);
1616

@@ -37,7 +37,7 @@ public void Test1()
3737
public void Test2()
3838
{
3939
var args = new TestArgs();
40-
var predicate = PredicateBuilder.True<TestObj>();
40+
var predicate = PredicateBuilder.New<TestObj>();
4141

4242
predicate = predicate.And(t => !args.Value);
4343

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.Threading.Tasks;
2+
using Abp.Notifications;
3+
using Shouldly;
4+
using Xunit;
5+
6+
namespace Abp.Zero.SampleApp.Tests.Notifications
7+
{
8+
public class UserNotificationManager_Tests : SampleAppTestBase
9+
{
10+
private readonly IUserNotificationManager _userNotificationManager;
11+
12+
public UserNotificationManager_Tests()
13+
{
14+
_userNotificationManager = Resolve<IUserNotificationManager>();
15+
}
16+
17+
[Fact]
18+
public async Task GetUserNotificationCountAsync_Test()
19+
{
20+
var notificationCount = await _userNotificationManager.GetUserNotificationCountAsync(
21+
new UserIdentifier(1, 2), UserNotificationState.Read
22+
);
23+
24+
notificationCount.ShouldBeGreaterThanOrEqualTo(0);
25+
}
26+
}
27+
}

0 commit comments

Comments
 (0)