using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Threading.Tasks; namespace Xamarin.PropertyEditing.Reflection { public class ReflectionEditorProvider : IEditorProvider { public IReadOnlyDictionary KnownTypes { get; } = new Dictionary { }; public Task GetObjectEditorAsync (object item) { return Task.FromResult (new ReflectionObjectEditor (item)); } public Task> GetPropertiesForTypeAsync (ITypeInfo type) { return Task.Run (() => { Type targetType = GetRealType (type); return (IReadOnlyCollection)GetPropertiesForType (targetType); }); } public Task CreateObjectAsync (ITypeInfo type) { var realType = GetRealType (type); if (realType == null) return Task.FromResult (null); object instance = Activator.CreateInstance (realType); return Task.FromResult (instance); } public Task GetAssignableTypesAsync (ITypeInfo type, bool childTypes) { return ReflectionObjectEditor.GetAssignableTypes (type, childTypes); } public Task> GetChildrenAsync (object item) { return Task.FromResult ((IReadOnlyList)Array.Empty ()); } public Task> GetKnownTypesAsync (IReadOnlyCollection knownTypes) { return Task.FromResult> (new Dictionary ()); } public ITypeInfo GetRealType (T item) { return item?.GetType ().ToTypeInfo (); } public static Type GetRealType (ITypeInfo type) { return Type.GetType ($"{type.NameSpace}.{type.Name}, {type.Assembly.Name}"); } public static IReadOnlyList GetPropertiesForType (Type targetType) { var properties = new List (); foreach (PropertyInfo property in targetType.GetProperties ()) { DebuggerBrowsableAttribute browsable = property.GetCustomAttribute (); if (browsable != null && browsable.State == DebuggerBrowsableState.Never) { continue; } if (CheckAvailability (property)) { if (property.PropertyType.IsEnum) { properties.Add ((ReflectionPropertyInfo)Activator.CreateInstance (typeof (ReflectionEnumPropertyInfo<>).MakeGenericType (Enum.GetUnderlyingType (property.PropertyType)), property)); } else { properties.Add (new ReflectionPropertyInfo (property)); } } } return properties; } private static Version OSVersion; private static bool CheckAvailability (PropertyInfo property) { Attribute availibility = property.GetCustomAttributes ().FirstOrDefault (a => a.GetType ().Name == "IntroducedAttribute"); if (availibility == null) return true; var versionProperty = availibility.GetType ().GetProperty ("Version"); if (versionProperty == null) return false; if (OSVersion == null) { Type processInfoType = Type.GetType ("Foundation.NSProcessInfo, Xamarin.Mac"); object processInfo = Activator.CreateInstance (processInfoType); object version = processInfoType.GetProperty ("OperatingSystemVersion").GetValue (processInfo); Type nsosversionType = version.GetType (); int major = (int)Convert.ChangeType (nsosversionType.GetField ("Major").GetValue (version), typeof(int)); int minor = (int)Convert.ChangeType (nsosversionType.GetField ("Minor").GetValue (version), typeof(int)); int build = (int)Convert.ChangeType (nsosversionType.GetField ("PatchVersion").GetValue (version), typeof(int)); OSVersion = new Version (major, minor, build); processInfoType.GetMethod ("Dispose").Invoke (processInfo, null); } Version available = (Version)versionProperty.GetValue (availibility); return (OSVersion >= available); } } }