Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/xamarin/Xamarin.PropertyEditing.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Maupin <ermaup@microsoft.com>2018-04-27 22:29:27 +0300
committerEric Maupin <ermaup@microsoft.com>2018-05-01 00:54:20 +0300
commit6733b45455489e7f23988e2a1a58a36710a4b957 (patch)
treee1fb08be0baa3bd073c2677a2c78f78d9426fb38 /Xamarin.PropertyEditing
parente4e840486c5b1a05a125a09c94b6ed2a7c08a40a (diff)
[Core] Make assignable types more reusable
Diffstat (limited to 'Xamarin.PropertyEditing')
-rw-r--r--Xamarin.PropertyEditing/AssignableTypesResult.cs22
-rw-r--r--Xamarin.PropertyEditing/Extensions.cs35
-rw-r--r--Xamarin.PropertyEditing/Reflection/ReflectionObjectEditor.cs38
-rw-r--r--Xamarin.PropertyEditing/ViewModels/ObjectPropertyViewModel.cs15
4 files changed, 81 insertions, 29 deletions
diff --git a/Xamarin.PropertyEditing/AssignableTypesResult.cs b/Xamarin.PropertyEditing/AssignableTypesResult.cs
index b16170a..94269ac 100644
--- a/Xamarin.PropertyEditing/AssignableTypesResult.cs
+++ b/Xamarin.PropertyEditing/AssignableTypesResult.cs
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
+using System.Linq;
+using Cadenza.Collections;
namespace Xamarin.PropertyEditing
{
public class AssignableTypesResult
{
- public AssignableTypesResult (IReadOnlyList<ITypeInfo> assignableTypes)
+ public AssignableTypesResult (IReadOnlyCollection<ITypeInfo> assignableTypes)
{
if (assignableTypes == null)
throw new ArgumentNullException (nameof(assignableTypes));
@@ -13,7 +15,7 @@ namespace Xamarin.PropertyEditing
AssignableTypes = assignableTypes;
}
- public AssignableTypesResult (IReadOnlyList<ITypeInfo> suggestedTypes, IReadOnlyList<ITypeInfo> assignableTypes)
+ public AssignableTypesResult (IReadOnlyList<ITypeInfo> suggestedTypes, IReadOnlyCollection<ITypeInfo> assignableTypes)
: this (assignableTypes)
{
if (suggestedTypes == null)
@@ -27,9 +29,23 @@ namespace Xamarin.PropertyEditing
get;
}
- public IReadOnlyList<ITypeInfo> AssignableTypes
+ public IReadOnlyCollection<ITypeInfo> AssignableTypes
{
get;
}
+
+ internal IReadOnlyDictionary<IAssemblyInfo, ILookup<string, ITypeInfo>> GetTypeTree ()
+ {
+ var assemblies = new Dictionary<IAssemblyInfo, ILookup<string, ITypeInfo>> ();
+ foreach (ITypeInfo type in AssignableTypes) {
+ if (!assemblies.TryGetValue (type.Assembly, out ILookup<string, ITypeInfo> types)) {
+ assemblies[type.Assembly] = types = new ObservableLookup<string, ITypeInfo> ();
+ }
+
+ ((IMutableLookup<string, ITypeInfo>) types).Add (type.NameSpace, type);
+ }
+
+ return assemblies;
+ }
}
} \ No newline at end of file
diff --git a/Xamarin.PropertyEditing/Extensions.cs b/Xamarin.PropertyEditing/Extensions.cs
index c6062c2..e789604 100644
--- a/Xamarin.PropertyEditing/Extensions.cs
+++ b/Xamarin.PropertyEditing/Extensions.cs
@@ -1,7 +1,8 @@
-using System;
+using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
+using System.Threading.Tasks;
namespace Xamarin.PropertyEditing
{
@@ -103,5 +104,37 @@ namespace Xamarin.PropertyEditing
return self.IndexOf (value, comparison) >= 0;
}
+
+ public static async Task<AssignableTypesResult> GetCommonAssignableTypes (this IEnumerable<IObjectEditor> editors, IPropertyInfo property, bool childTypes)
+ {
+ if (editors == null)
+ throw new ArgumentNullException (nameof(editors));
+ if (property == null)
+ throw new ArgumentNullException (nameof(property));
+
+ List<ITypeInfo> suggested = null;
+ HashSet<ITypeInfo> all = null;
+ var tasks = new HashSet<Task<AssignableTypesResult>> (editors.Select (oe => oe.GetAssignableTypesAsync (property, childTypes)));
+
+ while (tasks.Count > 0) {
+ var task = await Task.WhenAny (tasks).ConfigureAwait (false);
+ tasks.Remove (task);
+
+ if (suggested == null) {
+ suggested = new List<ITypeInfo> (task.Result.SuggestedTypes ?? Enumerable.Empty<ITypeInfo>());
+ all = new HashSet<ITypeInfo> (task.Result.AssignableTypes);
+ continue;
+ }
+
+ all.IntersectWith (task.Result.AssignableTypes);
+
+ foreach (ITypeInfo type in suggested.ToArray()) {
+ if (!task.Result.AssignableTypes.Contains (type))
+ suggested.Remove (type);
+ }
+ }
+
+ return new AssignableTypesResult (suggested, all);
+ }
}
}
diff --git a/Xamarin.PropertyEditing/Reflection/ReflectionObjectEditor.cs b/Xamarin.PropertyEditing/Reflection/ReflectionObjectEditor.cs
index 19b8d7d..a851b2e 100644
--- a/Xamarin.PropertyEditing/Reflection/ReflectionObjectEditor.cs
+++ b/Xamarin.PropertyEditing/Reflection/ReflectionObjectEditor.cs
@@ -94,18 +94,7 @@ namespace Xamarin.PropertyEditing.Reflection
public Task<AssignableTypesResult> GetAssignableTypesAsync (IPropertyInfo property, bool childTypes)
{
- return Task.Run (() => {
- ReflectionPropertyInfo realInfo = (ReflectionPropertyInfo) property;
- var assemblies = AppDomain.CurrentDomain.GetAssemblies ();
- var entry = Assembly.GetEntryAssembly();
-
- return new AssignableTypesResult (assemblies.Select (a => new { Assembly = a, Info = new AssemblyInfo (a.FullName, a == entry)})
- .SelectMany (a =>
- a.Assembly.DefinedTypes.Select (t => new { Type = t, Assembly = a }))
- .AsParallel ()
- .Where (t => realInfo.Type.IsAssignableFrom (t.Type))
- .Select (t => new TypeInfo (t.Assembly.Info, t.Type.Namespace, t.Type.Name)).ToList());
- });
+ return GetAssignableTypes (property, childTypes);
}
public async Task SetValueAsync<T> (IPropertyInfo property, ValueInfo<T> value, PropertyVariation variation = null)
@@ -138,6 +127,31 @@ namespace Xamarin.PropertyEditing.Reflection
};
}
+ internal static Task<AssignableTypesResult> GetAssignableTypes (IPropertyInfo property, bool childTypes)
+ {
+ return Task.Run (() => {
+ var types = AppDomain.CurrentDomain.GetAssemblies ().SelectMany (a => a.GetTypes ()).AsParallel ()
+ .Where (t => t.Namespace != null && !t.IsAbstract && !t.IsInterface && t.IsPublic && t.GetConstructor (Type.EmptyTypes) != null);
+
+ Type type = property.Type;
+ if (childTypes) {
+ var generic = property.Type.GetInterface ("ICollection`1");
+ if (generic != null) {
+ type = generic.GetGenericArguments()[0];
+ } else {
+ type = typeof(object);
+ }
+ }
+
+ types = types.Where (t => type.IsAssignableFrom (t));
+
+ return new AssignableTypesResult (types.Select (t => {
+ string asmName = t.Assembly.GetName ().Name;
+ return new TypeInfo (new AssemblyInfo (asmName, isRelevant: asmName.StartsWith ("Xamarin")), t.Namespace, t.Name);
+ }).ToList ());
+ });
+ }
+
private readonly object target;
private readonly List<ReflectionPropertyInfo> properties = new List<ReflectionPropertyInfo> ();
private readonly List<ReflectionEventInfo> events = new List<ReflectionEventInfo> ();
diff --git a/Xamarin.PropertyEditing/ViewModels/ObjectPropertyViewModel.cs b/Xamarin.PropertyEditing/ViewModels/ObjectPropertyViewModel.cs
index e491b23..af65bf8 100644
--- a/Xamarin.PropertyEditing/ViewModels/ObjectPropertyViewModel.cs
+++ b/Xamarin.PropertyEditing/ViewModels/ObjectPropertyViewModel.cs
@@ -233,19 +233,8 @@ namespace Xamarin.PropertyEditing.ViewModels
private async Task<IReadOnlyDictionary<IAssemblyInfo, ILookup<string, ITypeInfo>>> GetAssignableTypesAsync ()
{
- Task<AssignableTypesResult>[] typeTasks = Editors.Select (o => o.GetAssignableTypesAsync (Property, childTypes: false)).ToArray();
- AssignableTypesResult[] lists = await Task.WhenAll (typeTasks).ConfigureAwait (false);
-
- var assemblies = new Dictionary<IAssemblyInfo, ILookup<string, ITypeInfo>> ();
- foreach (ITypeInfo type in lists.SelectMany (t => t.AssignableTypes)) {
- if (!assemblies.TryGetValue (type.Assembly, out ILookup<string, ITypeInfo> types)) {
- assemblies[type.Assembly] = types = new ObservableLookup<string, ITypeInfo> ();
- }
-
- ((IMutableLookup<string, ITypeInfo>) types).Add (type.NameSpace, type);
- }
-
- return assemblies;
+ AssignableTypesResult result = await Editors.GetCommonAssignableTypes (Property, childTypes: false).ConfigureAwait (false);
+ return result.GetTypeTree ();
}
private async void CreateInstance ()