rd-net/RdFramework.Reflection/BindableChildrenUtil.cs (87 lines of code) (raw):

using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using JetBrains.Diagnostics; using JetBrains.Rd.Base; using JetBrains.Rd.Util; using JetBrains.Util; namespace JetBrains.Rd.Reflection { internal interface IReflectionBindable { List<KeyValuePair<string, object>> BindableChildren { get; } void OnActivated(); void EnsureBindableChildren(); } internal static class BindableChildrenUtil { private static readonly Dictionary<Type, Action<IReflectionBindable, PrettyPrinter>> ourPrettyPrinters = new Dictionary<Type, Action<IReflectionBindable, PrettyPrinter>>(); private static readonly Dictionary<Type, Action<IReflectionBindable>> ourFillBindableChildren = new Dictionary<Type, Action<IReflectionBindable>>(); private static readonly object ourPrettyPrintersLock = new object(); internal static void PrettyPrint(PrettyPrinter p, IReflectionBindable instance) { Action<IReflectionBindable, PrettyPrinter> prettyPrinter; lock (ourPrettyPrintersLock) { ourPrettyPrinters.TryGetValue(instance.GetType(), out prettyPrinter); } if (prettyPrinter == null) { var t = instance.GetType(); var header = t.Name + " ("; var bindableMembers = SerializerReflectionUtil.GetSerializableFields(t.GetTypeInfo()); var getters = bindableMembers.Select(ReflectionUtil.GetGetter).ToArray(); var intros = bindableMembers.Select(mi => $"{mi.Name} = ").ToArray(); prettyPrinter = (o, printer) => { printer.Print(header); using (printer.IndentCookie()) { for (int i = 0; i < getters.Length; i++) { printer.Print(intros[i]); getters[i](o).PrintEx(printer); printer.Println(); } } printer.Print(")"); }; lock (ourPrettyPrintersLock) { ourPrettyPrinters[t] = prettyPrinter; } } prettyPrinter(instance, p); } internal static void FillBindableFields(IReflectionBindable instance) { var type = instance.GetType(); Action<IReflectionBindable> fillBindableFields; lock (ourFillBindableChildren) { ourFillBindableChildren.TryGetValue(type, out fillBindableFields); } if (fillBindableFields == null) { var t = type; var bindableMembers = SerializerReflectionUtil.GetSerializableFields(t.GetTypeInfo()).ToArray(); var getters = bindableMembers.Select(ReflectionUtil.GetGetter).ToArray(); fillBindableFields = (obj) => { for (int i = 0; i < bindableMembers.Length; i++) { var value = getters[i](obj); // value can be null for fields primitive types in RdModels. They are used in serializations, but send their value on bind if (value != null) obj.BindableChildren.Add(new KeyValuePair<string, object>(bindableMembers[i].Name, value)); } }; lock (ourFillBindableChildren) { ourFillBindableChildren[t] = fillBindableFields; } } fillBindableFields(instance); } } }