예제 #1
0
        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
            }
        }
예제 #2
0
        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
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
 public ReflectionRdActivator(ReflectionSerializers serializers, [CanBeNull] IPolymorphicTypesCatalog polymorphicTypesCatalog)
 {
     mySerializers             = serializers;
     myPolymorphicTypesCatalog = polymorphicTypesCatalog;
 }