Пример #1
0
        private Lazy <IRelationMetadata> CreateRecursor(RelationMetadata metadata)
        {
            if (metadata.HasFlag(RelationMetadataFlags.Item))
            {
                IRelationMetadata recursiveParent = this.GetRecursiveParent(metadata);

                if (recursiveParent != null)
                {
                    string recursivePath = metadata.Notation.Path(recursiveParent.Identity.Name, metadata.Parent.Identity.Name);
                    string otherPath     = metadata.Notation.Combine(metadata.Identity.Name, recursivePath);

                    MetadataIdentity otherId = metadata.Identity.Push(recursivePath);

                    return(new Lazy <IRelationMetadata>(() => this.GetMetadata(metadata.Schema, otherId)));
                }
            }
            else if (metadata.Owner.Recursor != null)
            {
                IRelationContract contract = this.GetContract(metadata);

                if (contract != null && metadata.Owner.Type.Equals(contract.ItemType))
                {
                    return(new Lazy <IRelationMetadata>(() => metadata.Owner));
                }
            }

            return(null);
        }
        private void ValidateContract(RelationMetadata metadata, IRelationListContract contract)
        {
            if (contract.ItemType == null)
            {
                this.ThrowContractException(metadata, "Item type cannot be null.");
            }
            else if (string.IsNullOrWhiteSpace(contract.ItemName))
            {
                this.ThrowContractException(metadata, "Item name cannot be empty.");
            }
            else
            {
                Type enumerableType = typeof(IEnumerable <>).MakeGenericType(contract.ItemType);

                if (!enumerableType.IsAssignableFrom(metadata.Type))
                {
                    this.ThrowContractException(metadata, $"List of type '{metadata.Type.GetSanitizedName()}' cannot be converted to '{enumerableType.GetSanitizedName()}'.");
                }
            }

            if (contract.ReadIndex != null && !contract.ReadIndex.HasSignature(contract.ItemType, typeof(int)))
            {
                this.ThrowContractException(metadata, $"ReadIndex method must have signature '{contract.ItemType.GetSanitizedName()} (int)'.");
            }

            if (contract.WriteIndex != null && !contract.WriteIndex.HasSignature(typeof(void), typeof(int), contract.ItemType))
            {
                this.ThrowContractException(metadata, $"WriteIndex method must have signature 'void (int, {contract.ItemType.GetSanitizedName()})'.");
            }
        }
Пример #3
0
        private RelationMetadata CreateItem(RelationMetadata parent)
        {
            if (parent.Owner.HasFlag(RelationMetadataFlags.Recursive))
            {
                MemberInfo parentMember = parent.Owner.Parent?.Member;
                MemberInfo thisMember   = parent.Member;

                if (parentMember != null && parentMember.Equals(thisMember))
                {
                    return(null);
                }
            }

            IRelationContract contract = this.GetContract(parent);

            if (contract == null)
            {
                return(null);
            }

            MetadataIdentity itemId   = parent.Identity.Push(contract.ItemName ?? "Item");
            RelationMetadata metadata = new RelationMetadata(parent.Schema, itemId)
            {
                Parent     = parent,
                Type       = contract.ItemType,
                Flags      = RelationMetadataFlags.Item,
                ReadIndex  = contract.ReadIndex,
                WriteIndex = contract.WriteIndex,
                Depth      = parent.Depth + 1,
            };

            metadata.Owner       = metadata;
            metadata.Item        = this.CreateItem(metadata);
            metadata.Properties  = this.CreateLazy(() => this.CreateProperties(metadata));
            metadata.Annotations = this.CreateAnnotations(metadata).ToList();

            if (contract.ReadIndex != null)
            {
                metadata.Flags |= RelationMetadataFlags.Readable;
            }

            if (contract.WriteIndex != null)
            {
                metadata.Flags |= RelationMetadataFlags.Writable;
            }

            if (metadata.Item != null)
            {
                metadata.Flags |= RelationMetadataFlags.List;
            }

            return(metadata);
        }
        private IRelationListContract GetListContract(RelationMetadata metadata)
        {
            IEnumerable <IRelationContractResolver> allResolvers = new[] { this.DefaultResolver }.Concat(this);

            IRelationListContract contract = allResolvers.Reverse().NotNull(cr => cr.GetListContract(metadata)).FirstOrDefault();

            if (contract != null)
            {
                this.ValidateContract(metadata, contract);
            }

            return(contract);
        }
Пример #5
0
        private RelationMetadata CreateProperty(RelationMetadata parent, MemberInfo memberInfo)
        {
            MetadataIdentity propertyId = parent.Identity.Push(memberInfo.Name);

            RelationMetadata metadata = new RelationMetadata(parent.Schema, propertyId)
            {
                Type   = this.GetMemberType(memberInfo),
                Parent = parent,
                Member = memberInfo,
                Owner  = parent.Owner,
                Flags  = RelationMetadataFlags.Property,
                Depth  = parent.Depth,
            };

            metadata.Item        = this.CreateItem(metadata);
            metadata.Properties  = this.CreateLazy(() => this.CreateProperties(metadata));
            metadata.Annotations = this.CreateAnnotations(metadata).ToList();

            if (metadata.Item != null)
            {
                metadata.Flags |= RelationMetadataFlags.List;
            }

            if (memberInfo is PropertyInfo pi)
            {
                if (pi.CanRead)
                {
                    metadata.Flags |= RelationMetadataFlags.Readable;
                }

                if (pi.CanWrite)
                {
                    metadata.Flags |= RelationMetadataFlags.Writable;
                }
            }
            else if (memberInfo is FieldInfo)
            {
                metadata.Flags |= RelationMetadataFlags.Readable | RelationMetadataFlags.Writable;
            }

            parent.Schema.AddMetadata <IRelationMetadata>(metadata);

            if (metadata.Item != null)
            {
                parent.Schema.AddMetadata <IRelationMetadata>(metadata.Item);
            }

            this.AddRecursors(metadata);

            return(metadata);
        }
Пример #6
0
        private IEnumerable <RelationMetadata> CreateProperties(RelationMetadata parent)
        {
            IEnumerable <MemberInfo> members = parent.Type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            foreach (MemberInfo member in members.Where(m => this.IsFieldOrNonIndexedProperty(m)))
            {
                RelationMetadata property = this.CreateProperty(parent, member);

                if (property != null)
                {
                    yield return(property);
                }
            }
        }
        private RelationMetadata CreateItem(IMetadataBuilderContext context, RelationMetadata parent)
        {
            IRelationListContract contract = this.GetListContract(parent);

            if (contract == null)
            {
                return(null);
            }

            MetadataIdentity itemId = parent.Identity.Child(contract.ItemName ?? "Item");

            RelationMetadata metadata = new RelationMetadata(itemId)
            {
                Parent     = parent,
                Type       = contract.ItemType,
                Flags      = RelationMetadataFlags.Item | RelationMetadataFlags.Property,
                ReadIndex  = contract.ReadIndex,
                WriteIndex = contract.WriteIndex,
            };

            metadata.MemberOf    = metadata;
            metadata.Item        = this.CreateItem(context, metadata);
            metadata.Properties  = this.CreateLazy(() => this.CreateProperties(context, metadata));
            metadata.Annotations = this.CreateAnnotations(metadata).ToList();

            if (this.IsMetadataRecursive(metadata))
            {
                metadata.Flags |= RelationMetadataFlags.Recursive;
            }

            if (contract.ReadIndex != null)
            {
                metadata.Flags |= RelationMetadataFlags.Readable;
            }

            if (contract.WriteIndex != null)
            {
                metadata.Flags |= RelationMetadataFlags.Writable;
            }

            if (metadata.Item != null)
            {
                metadata.Flags |= RelationMetadataFlags.List;
            }

            context.AddMetadata <IRelationMetadata>(metadata);

            return(metadata);
        }
        private RelationMetadata CreateProperty(IMetadataBuilderContext context, RelationMetadata parent, MemberInfo memberInfo)
        {
            MetadataIdentity attributeId = parent.Identity.Child(memberInfo.Name);

            RelationMetadata metadata = new RelationMetadata(attributeId)
            {
                Type     = this.GetMemberType(memberInfo),
                Parent   = parent,
                Member   = memberInfo,
                MemberOf = parent.MemberOf,
                Flags    = RelationMetadataFlags.Property,
            };

            metadata.Item        = this.CreateItem(context, metadata);
            metadata.Properties  = this.CreateLazy(() => this.CreateProperties(context, metadata));
            metadata.Annotations = this.CreateAnnotations(metadata).ToList();

            if (metadata.Item != null)
            {
                metadata.Flags |= RelationMetadataFlags.List;
            }

            if (this.IsMetadataRecursive(metadata))
            {
                metadata.Flags |= RelationMetadataFlags.Recursive;
            }

            if (memberInfo is PropertyInfo pi)
            {
                if (pi.CanRead)
                {
                    metadata.Flags |= RelationMetadataFlags.Readable;
                }

                if (pi.CanWrite)
                {
                    metadata.Flags |= RelationMetadataFlags.Writable;
                }
            }
            else if (memberInfo is FieldInfo)
            {
                metadata.Flags |= RelationMetadataFlags.Readable | RelationMetadataFlags.Writable;
            }

            context.AddMetadata <IRelationMetadata>(metadata);

            return(metadata);
        }
Пример #9
0
        private IRelationMetadata GetRecursiveParent(RelationMetadata metadata)
        {
            IRelationMetadata current = metadata.Parent;
            IRelationMetadata stop    = current.Owner.Parent ?? current.Owner;

            while (current != stop)
            {
                if (current.Type == metadata.Type)
                {
                    return(current);
                }

                current = current.Parent;
            }

            return(null);
        }
Пример #10
0
        private void AddRecursors(RelationMetadata metadata)
        {
            metadata.Recursor = this.CreateRecursor(metadata);

            if (metadata.Recursor != null)
            {
                metadata.Flags |= RelationMetadataFlags.Recursive | RelationMetadataFlags.List;
            }

            if (metadata.Item != null)
            {
                metadata.Item.Recursor = this.CreateRecursor(metadata.Item);

                if (metadata.Item.Recursor != null)
                {
                    metadata.Item.Flags |= RelationMetadataFlags.Recursive;
                }
            }
        }
Пример #11
0
        public void Initialize(IMetadataBuilderContext context)
        {
            RelationMetadata model = new RelationMetadata(context.Identity)
            {
                Flags = RelationMetadataFlags.Model | RelationMetadataFlags.Readable,
                Type  = context.Schema.Model,
            };

            model.MemberOf   = model;
            model.Properties = this.CreateLazy(() => this.CreateProperties(context, model));

            model.Annotations = this.CreateAnnotations(model).ToList();
            model.Item        = this.CreateItem(context, model);

            if (model.Item != null)
            {
                model.Flags |= RelationMetadataFlags.List;
            }

            context.AddMetadata <IRelationMetadata>(model);
        }
Пример #12
0
        internal void Initialize(Schema schema, Type modelType)
        {
            MetadataIdentity identity = new MetadataIdentity(schema);
            RelationMetadata metadata = new RelationMetadata(schema, identity)
            {
                Flags = RelationMetadataFlags.Model | RelationMetadataFlags.Readable,
                Type  = modelType,
            };

            metadata.Owner      = metadata;
            metadata.Properties = this.CreateLazy(() => this.CreateProperties(metadata));
            metadata.Depth      = 0;

            metadata.Annotations = this.CreateAnnotations(metadata).ToList();
            metadata.Item        = this.CreateItem(metadata);

            if (metadata.Item != null)
            {
                metadata.Flags |= RelationMetadataFlags.List;
            }

            schema.AddMetadata <IRelationMetadata>(metadata);
        }
Пример #13
0
        private IEnumerable <RelationMetadata> CreateProperties(IMetadataBuilderContext context, RelationMetadata parent)
        {
            IEnumerable <MemberInfo> members = parent.Type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            foreach (MemberInfo member in members.Where(m => this.IsFieldOrNonIndexedProperty(m)))
            {
                yield return(this.CreateProperty(context, parent, member));
            }
        }
Пример #14
0
        private IEnumerable <Attribute> CreateAnnotations(RelationMetadata metadata)
        {
            IEnumerable <IRelationContractResolver> allResolvers = new[] { this.DefaultResolver }.Concat(this);

            return(allResolvers.NotNull().SelectMany(cr => cr.GetAnnotationContract(metadata) ?? Array.Empty <Attribute>()).NotNull());
        }
Пример #15
0
 private void ThrowContractException(RelationMetadata metadata, string message)
 {
     throw new MetadataBuilderException($"Invalid contract for metadata '{metadata.Identity}'. {message}");
 }