private static ModelPropertyFlags RemoveFlag(ModelPropertyFlags flag, ModelPropertyFlags accumulatedFlags, ModelPropertyFlags propertyFlags) { if (!propertyFlags.HasFlag(flag)) { return(accumulatedFlags & ~flag); } else { return(accumulatedFlags); } }
private static ModelPropertyFlags AddFlag(ModelPropertyFlags flag, ModelPropertyFlags accumulatedFlags, ModelPropertyFlags propertyFlags) { if (propertyFlags.HasFlag(flag)) { return(accumulatedFlags | flag); } else { return(accumulatedFlags); } }
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; }
internal ComplexSlot(ModelPropertyFlags flags, ModelProperty effectiveProperty) { this.flags = flags; this.effectiveProperty = effectiveProperty; }
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; } }
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; } }