blob: 904cfa4ca57e3b8beae6b109e3ea6db02877d36a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Xamarin.PropertyEditing
{
/// <summary>
/// Represents groups of availability constraints that are ORed together.
/// </summary>
/// <remarks>
/// The individual availability constraints are ANDed together within the group to produce the groups' result.
/// The groups are ORed together, so only one needs to have its constituents all true.
/// </remarks>
public class MultiAvailabilityConstraint
: IAvailabilityConstraint
{
public MultiAvailabilityConstraint (IEnumerable<IEnumerable<IAvailabilityConstraint>> constraintGroups)
{
if (constraintGroups == null)
throw new ArgumentNullException (nameof(constraintGroups));
List<IPropertyInfo> properties = new List<IPropertyInfo> ();
this.constraints = new List<List<IAvailabilityConstraint>> ();
foreach (var g in constraintGroups) {
var group = new List<IAvailabilityConstraint> ();
foreach (var c in g) {
if (c.ConstrainingProperties != null) {
foreach (var p in c.ConstrainingProperties) {
if (!properties.Contains (p))
properties.Add (p);
}
}
group.Add (c);
}
this.constraints.Add (group);
}
ConstrainingProperties = properties;
}
public IReadOnlyList<IPropertyInfo> ConstrainingProperties {
get;
}
public async Task<bool> GetIsAvailableAsync (IObjectEditor editor)
{
HashSet<Task<bool>> tasks = new HashSet<Task<bool>> ();
for (int i = 0; i < this.constraints.Count; i++) {
tasks.Add (Task.WhenAll (this.constraints[i].Select (c => c.GetIsAvailableAsync (editor)).ToArray ())
.ContinueWith (t => {
if (t.IsFaulted)
return false;
return Array.TrueForAll (t.Result, b => b);
}, TaskScheduler.Default));
}
// The groups of constraints are ||ed, each group's constraints are &&ed
while (tasks.Count > 0) {
var task = await Task.WhenAny (tasks).ConfigureAwait (false);
if (task.IsFaulted)
return false;
if (task.Result)
return true;
tasks.Remove (task);
}
return false;
}
private readonly List<List<IAvailabilityConstraint>> constraints;
}
}
|