public static void AssertValidRdModel([NotNull] TypeInfo type) { var isDataModel = HasRdModelAttribute(type); Assertion.Assert(isDataModel, $"Error in {type.ToString(true)} model: no {nameof(RdModelAttribute)} attribute specified"); Assertion.Assert(!type.IsValueType, $"Error in {type.ToString(true)} model: data model can't be ValueType"); // No way to prevent serialization errors for intrinsic serializers, just skip for now if (HasIntrinsicMethods(type)) { return; } foreach (var member in ReflectionSerializers.GetBindableMembers(type)) { if (member is PropertyInfo || member is FieldInfo) { AssertDataMemberDeclaration(member); } if (member is TypeInfo) { // out scope for current validation } // methods events are allowed in model } }
public static void AssertValidRdExt(TypeInfo type) { var isRdModel = HasRdExtAttribute(type); Assertion.Assert(isRdModel, $"Error in {type.ToString(true)} model: no {nameof(RdExtAttribute)} attribute specified"); Assertion.Assert(!type.IsValueType, $"Error in {type.ToString(true)} model: can't be ValueType"); Assertion.Assert(typeof(RdReflectionBindableBase).GetTypeInfo().IsAssignableFrom(type.AsType()), $"Error in {type.ToString(true)} model: should be inherited from {nameof(RdReflectionBindableBase)}"); // actually, it is possible, but error-prone. // you may have non-rdmodel base class and several sealed derivatives from it. // commented sealed check to avoid annoying colleagues. // Assertion.Assert(type.IsSealed, $"Error in {type.ToString(true)} model: RdModels must be sealed."); foreach (var member in ReflectionSerializers.GetBindableMembers(type)) { if (member is PropertyInfo || member is FieldInfo) { AssertMemberDeclaration(member); } if (member is TypeInfo) { // out scope for current validation } // methods and events are allowed in model } }
private object ActivateRd(Type type) { #if JET_MODE_ASSERT Assertion.Assert(!myCurrentActivationChain.Contains(type), $"Unable to activate {type.FullName}: circular dependency detected: {string.Join(" -> ", myCurrentActivationChain.Select(t => t.FullName).ToArray())}"); myCurrentActivationChain.Enqueue(type); #endif var typeInfo = type.GetTypeInfo(); ReflectionSerializerVerifier.AssertValidRdExt(typeInfo); var implementingType = ReflectionSerializerVerifier.GetImplementingType(typeInfo); Assertion.Assert(typeof(IRdBindable).GetTypeInfo().IsAssignableFrom(implementingType), $"Unable to activate {type.FullName}: type should be {nameof(IRdBindable)}"); var instance = Activator.CreateInstance(implementingType); var implementingTypeInfo = implementingType.GetTypeInfo(); foreach (var mi in ReflectionSerializers.GetBindableMembers(implementingTypeInfo)) { ReflectionSerializerVerifier.AssertMemberDeclaration(mi); var currentValue = ReflectionUtil.GetGetter(mi)(instance); if (currentValue == null) { currentValue = ActivateRdExtMember(mi); var memberSetter = ReflectionUtil.GetSetter(mi); memberSetter(instance, currentValue); } } #if JET_MODE_ASSERT myCurrentActivationChain.Dequeue(); #endif // Allow initialize to setup bindings to composite properties. if (instance is RdReflectionBindableBase reflectionBindable) { reflectionBindable.OnActivated(); } return(instance); }
public override void Print(PrettyPrinter p) { Action <RdReflectionBindableBase, PrettyPrinter> prettyPrinter; lock (ourPrettyPrintersLock) { ourPrettyPrinters.TryGetValue(GetType(), out prettyPrinter); } if (prettyPrinter == null) { var t = GetType(); var header = t.Name + " ("; var bindableMembers = ReflectionSerializers.GetBindableMembers(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(this, p); }
protected void EnsureBindableChildren() { if (bindableChildrenFilled) { return; } bindableChildrenFilled = true; Action <RdReflectionBindableBase> fillBindableFields; lock (ourFillBindableChildren) { ourFillBindableChildren.TryGetValue(GetType(), out fillBindableFields); } if (fillBindableFields == null) { var t = GetType(); var bindableMembers = ReflectionSerializers.GetBindableMembers(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); obj.BindableChildren.Add(new KeyValuePair <string, object>(bindableMembers[i].Name, value)); } }; lock (ourFillBindableChildren) { ourFillBindableChildren[t] = fillBindableFields; } } fillBindableFields(this); }
public ReflectionRdActivator(ReflectionSerializers serializers, [CanBeNull] IPolymorphicTypesCatalog polymorphicTypesCatalog) { mySerializers = serializers; myPolymorphicTypesCatalog = polymorphicTypesCatalog; }