示例#1
0
        private ModelProperty(ModelObjectDescriptor declaringDescriptor, string name, Type immutableType, Type mutableType, Func <MetaProperty> metaProperty, object defaultValue)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }
            if (immutableType == null)
            {
                throw new ArgumentNullException(nameof(immutableType));
            }
            if (mutableType == null)
            {
                throw new ArgumentNullException(nameof(mutableType));
            }
            this.declaringDescriptor = declaringDescriptor;
            this.name  = name;
            this.flags = ModelPropertyFlags.None;
            if (typeof(IModelObject).IsAssignableFrom(immutableType) || typeof(IModelObject).IsAssignableFrom(mutableType))
            {
                this.flags |= ModelPropertyFlags.ModelObject;
            }
            this.immutableType = immutableType;
            this.mutableType   = mutableType;
            FieldInfo info = declaringDescriptor.DescriptorType.GetField(name + "Property", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);

            if (info == null)
            {
                throw new InvalidOperationException("Cannot find static field '" + name + "Property' in " + declaringDescriptor.DescriptorType.FullName + ".");
            }
            this.annotations         = info.GetCustomAttributes().ToImmutableArray();
            this.state               = ModelPropertyInitState.None;
            this.subsettedProperties = ImmutableArray <ModelProperty> .Empty;
            this.redefinedProperties = ImmutableArray <ModelProperty> .Empty;
            this.oppositeProperties  = ImmutableArray <ModelProperty> .Empty;
            if (metaProperty != null)
            {
                this.metaProperty = new Lazy <MetaProperty>(metaProperty, true);
            }
            else
            {
                this.metaProperty = new Lazy <MetaProperty>(() => null, true);
            }
            this.defaultValue = defaultValue;
        }
示例#2
0
        public void Initialize()
        {
            if (this.state == ModelPropertyInitState.Initialized)
            {
                return;
            }
            lock (ModelProperty.lockObject)
            {
                if (this.state == ModelPropertyInitState.Initialized)
                {
                    return;
                }
                if (this.state == ModelPropertyInitState.None)
                {
                    this.InitializeFlags();
                }
                var subsettedPropertiesBuilder = ArrayBuilder <ModelProperty> .GetInstance();

                var redefinedPropertiesBuilder = ArrayBuilder <ModelProperty> .GetInstance();

                var oppositePropertiesBuilder = ArrayBuilder <ModelProperty> .GetInstance();

                foreach (var annot in this.annotations)
                {
                    if (annot is SubsetsAttribute)
                    {
                        SubsetsAttribute      propAnnot  = (SubsetsAttribute)annot;
                        ModelObjectDescriptor descriptor = ModelObjectDescriptor.GetDescriptorForDescriptorType(propAnnot.DeclaringType);
                        ModelProperty         prop       = descriptor.GetDeclaredProperty(propAnnot.PropertyName);
                        if (prop == null)
                        {
                            throw new InvalidOperationException("Error subsetting property: " + this.FullDeclaredName + "->" + prop.FullDeclaredName + ". The subsetted property cannot be found.");
                        }
                        if ((descriptor == this.declaringDescriptor || this.declaringDescriptor.AllBaseDescriptors.Contains(descriptor)))
                        {
                            if (!this.IsUnique)
                            {
                                throw new InvalidOperationException("Error subsetting property: " + this.FullDeclaredName + "->" + prop.FullDeclaredName + ". The subsetting property must be a collection of unique values.");
                            }
                            if (!prop.IsUnique)
                            {
                                throw new InvalidOperationException("Error subsetting property: " + this.FullDeclaredName + "->" + prop.FullDeclaredName + ". The subsetted property must be a collection of unique values.");
                            }
                            subsettedPropertiesBuilder.Add(prop);
                        }
                        else
                        {
                            throw new InvalidOperationException("Error subsetting property: " + this.FullDeclaredName + "->" + prop.FullDeclaredName + ". The subsetted property must come from the current type or from a base type.");
                        }
                    }
                    else if (annot is RedefinesAttribute)
                    {
                        RedefinesAttribute    propAnnot  = (RedefinesAttribute)annot;
                        ModelObjectDescriptor descriptor = ModelObjectDescriptor.GetDescriptorForDescriptorType(propAnnot.DeclaringType);
                        ModelProperty         prop       = descriptor.GetDeclaredProperty(propAnnot.PropertyName);
                        if (prop == null)
                        {
                            throw new InvalidOperationException("Error redefining property: " + this.FullDeclaredName + "->" + prop.FullDeclaredName + ". The redefined property cannot be found.");
                        }
                        if ((descriptor == this.declaringDescriptor || this.declaringDescriptor.AllBaseDescriptors != null && this.declaringDescriptor.AllBaseDescriptors.Contains(descriptor)))
                        {
                            if (this.IsContainment && !prop.IsContainment)
                            {
                                throw new InvalidOperationException("Error redefining property: " + this.FullDeclaredName + "->" + prop.FullDeclaredName + ". The redefining property cannot be a containment if the redefined property is not a containment.");
                            }
                            redefinedPropertiesBuilder.Add(prop);
                        }
                        else
                        {
                            throw new InvalidOperationException("Error redefining property: " + this.FullDeclaredName + "->" + prop.FullDeclaredName + ". The redefined property must come from the current type or from a base type.");
                        }
                    }
                    else if (annot is OppositeAttribute)
                    {
                        OppositeAttribute     propAnnot  = (OppositeAttribute)annot;
                        ModelObjectDescriptor descriptor = ModelObjectDescriptor.GetDescriptorForDescriptorType(propAnnot.DeclaringType);
                        ModelProperty         prop       = descriptor.GetDeclaredProperty(propAnnot.PropertyName);
                        if (prop == null)
                        {
                            throw new InvalidOperationException("Error in setting opposite property: " + this.FullDeclaredName + "->" + propAnnot.DeclaringType + "." + propAnnot.PropertyName + ". The opposite property cannot be found.");
                        }
                        bool foundThisProperty = false;
                        foreach (var oppositeAnnot in prop.annotations)
                        {
                            if (oppositeAnnot is OppositeAttribute)
                            {
                                OppositeAttribute propOppositeAnnot = (OppositeAttribute)oppositeAnnot;
                                if (propOppositeAnnot.DeclaringType == this.declaringDescriptor.DescriptorType &&
                                    propOppositeAnnot.PropertyName == this.name)
                                {
                                    foundThisProperty = true;
                                    break;
                                }
                            }
                        }
                        if (foundThisProperty)
                        {
                            oppositePropertiesBuilder.Add(prop);
                        }
                        else
                        {
                            throw new InvalidOperationException("Error in setting opposite property: " + this.FullDeclaredName + "->" + prop.FullDeclaredName + ". Opposite properties must be mutual.");
                        }
                    }
                    else if (annot is DerivedUnionAttribute)
                    {
                        if (!this.IsUnique)
                        {
                            throw new InvalidOperationException("Error in property: " + this.FullDeclaredName + ". A derived union property must be contain unique values.");
                        }
                        this.flags |= ModelPropertyFlags.DerivedUnion | ModelPropertyFlags.Readonly;
                    }
                }
                subsettedProperties = subsettedPropertiesBuilder.ToImmutableAndFree();
                redefinedProperties = redefinedPropertiesBuilder.ToImmutableAndFree();
                oppositeProperties  = oppositePropertiesBuilder.ToImmutableAndFree();
                this.state          = ModelPropertyInitState.Initialized;
            }
        }
示例#3
0
 private void InitializeFlags()
 {
     if (this.state == ModelPropertyInitState.Initialized)
     {
         return;
     }
     lock (ModelProperty.lockObject)
     {
         if (this.state == ModelPropertyInitState.Initialized)
         {
             return;
         }
         foreach (var annot in this.annotations)
         {
             if (annot is ReadonlyAttribute)
             {
                 this.flags |= ModelPropertyFlags.Readonly;
             }
             else if (annot is DerivedAttribute)
             {
                 this.flags |= ModelPropertyFlags.Derived | ModelPropertyFlags.Readonly;
             }
             else if (annot is CollectionAttribute)
             {
                 this.flags |= ModelPropertyFlags.Collection;
             }
             else if (annot is OrderedAttribute)
             {
                 this.flags |= ModelPropertyFlags.Ordered;
             }
             else if (annot is NonUniqueAttribute)
             {
                 this.flags |= ModelPropertyFlags.NonUnique;
             }
             else if (annot is NonNullAttribute)
             {
                 this.flags |= ModelPropertyFlags.NonNull;
             }
             else if (annot is ContainmentAttribute)
             {
                 this.flags |= ModelPropertyFlags.Containment;
             }
             else if (annot is NameAttribute)
             {
                 this.metaFlags |= MetaModelPropertyFlags.Name;
             }
             else if (annot is TypeAttribute)
             {
                 this.metaFlags |= MetaModelPropertyFlags.Type;
             }
             else if (annot is MemberAttribute)
             {
                 this.metaFlags |= MetaModelPropertyFlags.Member;
             }
             else if (annot is NonMemberAttribute)
             {
                 this.metaFlags |= MetaModelPropertyFlags.NonMember;
             }
             else if (annot is ImportAttribute)
             {
                 this.metaFlags |= MetaModelPropertyFlags.Import;
             }
             else if (annot is BaseScopeAttribute)
             {
                 this.metaFlags |= MetaModelPropertyFlags.BaseScope;
             }
         }
         this.state = ModelPropertyInitState.FlagsSet;
     }
 }