private void AddMemberField(CodeTypeDeclaration classDeclaration, PropertyData property) { if (property.IsJoinedKey) { classDeclaration.Members.Add(GetJoinedKeyProperty(property)); } else { CodeMemberField memberField = null; // Soooo ugly. switch (property.PropertyType) { case PropertyType.Property: memberField = GetMemberFieldOfProperty(property, Accessor.Private); CodeMemberProperty memberProperty = GetActiveRecordMemberProperty(memberField, property); classDeclaration.Members.Add(memberProperty); if (property.IsValidatorSet) memberProperty.CustomAttributes.AddRange(property.GetValidationAttributes()); break; case PropertyType.Field: memberField = GetMemberFieldOfProperty(property, property.Accessor); memberField.CustomAttributes.Add(property.GetFieldAttribute()); break; case PropertyType.Version: memberField = GetMemberFieldOfProperty(property, Accessor.Private); classDeclaration.Members.Add(GetActiveRecordMemberVersion(memberField, property)); break; case PropertyType.Timestamp: memberField = GetMemberFieldOfProperty(property, Accessor.Private); classDeclaration.Members.Add(GetActiveRecordMemberTimestamp(memberField, property)); break; } classDeclaration.Members.Add(memberField); } }
private CodeMemberProperty GetJoinedKeyProperty(PropertyData property) { string basePropertyName = property.ModelClass.PrimaryKey.Name; CodeTypeReference basePropertyType = GetPropertyType(property.ModelClass.PrimaryKey); CodeMemberProperty memberProperty = new CodeMemberProperty(); memberProperty.CustomAttributes.Add(property.GetPrimaryKeyAttribute()); memberProperty.Attributes = MemberAttributes.Public; if (Context.Model.UseVirtualProperties) { if (property.Name == basePropertyName) memberProperty.Attributes |= MemberAttributes.Override; } else { memberProperty.Attributes |= MemberAttributes.Final; if (property.Name == basePropertyName) memberProperty.Attributes |= MemberAttributes.New; } memberProperty.Name = property.Name; memberProperty.Type = basePropertyType; memberProperty.HasGet = true; memberProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodePropertyReferenceExpression(new CodeBaseReferenceExpression(), basePropertyName))); memberProperty.HasSet = true; memberProperty.SetStatements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(new CodeBaseReferenceExpression(), basePropertyName), new CodeVariableReferenceExpression("value"))); return memberProperty; }
private CodeMemberField GetMemberFieldOfProperty(PropertyData property, Accessor accessor) { return GetMemberField(property.Name, GetPropertyType(property), accessor, property.EffectiveAccess); }
private CodeTypeReference GetPropertyType(PropertyData property) { if (Context.Model.UseNullables != NullableUsage.No && TypeHelper.IsNullable(property.ColumnType) && !property.NotNull) { if (Context.Model.UseNullables == NullableUsage.WithHelperLibrary) return TypeHelper.GetNullableTypeReferenceForHelper(property.ColumnType); return TypeHelper.GetNullableTypeReference(property.ColumnType); } return new CodeTypeReference(TypeHelper.GetSystemType(property.ColumnType, property.CustomMemberType)); }
private CodeMemberProperty GetActiveRecordMemberTimestamp(CodeMemberField memberField, PropertyData property) { CodeMemberProperty memberProperty = GetMemberProperty(memberField, property.Name, property.ColumnType, null, property.NotNull, true, true, property.ImplementsINotifyPropertyChanged(), property.ImplementsINotifyPropertyChanging(), property.Description); memberProperty.CustomAttributes.Add(property.GetTimestampAttribute()); return memberProperty; }
private CodeMemberProperty GetActiveRecordMemberProperty(CodeMemberField memberField, PropertyData property) { CodeMemberProperty memberProperty = GetMemberProperty(memberField, property.Name, property.ColumnType, property.CustomMemberType, property.NotNull, true, true, property.ImplementsINotifyPropertyChanged(), property.ImplementsINotifyPropertyChanging(), property.Description); CodeAttributeDeclaration attributeDecleration = null; switch (property.KeyType) { // Composite keys must be handled in upper levels case KeyType.None: attributeDecleration = property.GetPropertyAttribute(); break; case KeyType.PrimaryKey: attributeDecleration = property.GetPrimaryKeyAttribute(); break; } memberProperty.CustomAttributes.Add(attributeDecleration); return memberProperty; }
private CodeTypeDeclaration GetCompositeClassDeclaration(CodeNamespace nameSpace, CodeTypeDeclaration parentClass, List<ModelProperty> keys, bool implementINotifyPropertyChanged) { if (keys == null || keys.Count <= 1) throw new ArgumentException("Composite keys must consist of two or more properties.", "keys"); string className = null; foreach (ModelProperty property in keys) { if (!string.IsNullOrEmpty(property.CompositeKeyName)) { className = property.CompositeKeyName; break; } } if (string.IsNullOrEmpty(className)) className = parentClass.Name + Common.CompositeClassNameSuffix; CodeTypeDeclaration classDeclaration = CreateClass(className); if (implementINotifyPropertyChanged) { classDeclaration.BaseTypes.Add(new CodeTypeReference(Common.INotifyPropertyChangedType)); AddINotifyPropertyChangedRegion(classDeclaration, Context.Model.UseVirtualProperties); } classDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("Serializable")); if (keys[0].ModelClass.Model.UseGeneratedCodeAttribute) classDeclaration.CustomAttributes.Add(AttributeHelper.GetGeneratedCodeAttribute()); List<CodeMemberField> fields = new List<CodeMemberField>(); List<string> descriptions = new List<string>(); foreach (ModelProperty property in keys) { PropertyData propertyData = new PropertyData(property); CodeMemberField memberField = GetMemberFieldOfProperty(propertyData, Accessor.Private); classDeclaration.Members.Add(memberField); fields.Add(memberField); classDeclaration.Members.Add(GetActiveRecordMemberKeyProperty(memberField, propertyData)); if (!String.IsNullOrEmpty(property.Description)) descriptions.Add(property.Description); } if (descriptions.Count > 0) classDeclaration.Comments.AddRange(GetSummaryComment(descriptions.ToArray())); classDeclaration.Members.Add(GetCompositeClassToStringMethod(fields)); classDeclaration.Members.Add(GetCompositeClassEqualsMethod(className, fields)); classDeclaration.Members.AddRange(GetCompositeClassGetHashCodeMethods(fields)); nameSpace.Types.Add(classDeclaration); return classDeclaration; }
private CodeTypeDeclaration GenerateClass(ModelClass cls, CodeNamespace nameSpace, TemplateMemberGenerator templateMemberGenerator) { if (cls == null) throw new ArgumentNullException("cls", "Class not supplied"); if (nameSpace == null) throw new ArgumentNullException("nameSpace", "Namespace not supplied"); if (String.IsNullOrEmpty(cls.Name)) throw new ArgumentException("Class name cannot be blank", "cls"); CodeTypeDeclaration classDeclaration = GetClassDeclaration(cls, nameSpace); GenerateCommonPrimaryKey(cls, classDeclaration); List<ModelProperty> compositeKeys = new List<ModelProperty>(); // Properties and Fields foreach (ModelProperty property in cls.Properties) { PropertyData propertyData = new PropertyData(property); if (property.KeyType != KeyType.CompositeKey) { AddMemberField(classDeclaration, propertyData); if (property.DebuggerDisplay) classDeclaration.CustomAttributes.Add(propertyData.GetDebuggerDisplayAttribute()); if (property.DefaultMember) classDeclaration.CustomAttributes.Add(propertyData.GetDefaultMemberAttribute()); } else compositeKeys.Add(property); } if (compositeKeys.Count > 0) { CodeTypeDeclaration compositeClass = GetCompositeClassDeclaration(nameSpace, classDeclaration, compositeKeys, cls.DoesImplementINotifyPropertyChanged()); // TODO: All access fields in a composite group assumed to be the same. // We have a model validator for this case but the user may save anyway. // Check if all access fields are the same. CodeMemberField memberField = GetPrivateMemberFieldOfCompositeClass(compositeClass, PropertyAccess.Property); classDeclaration.Members.Add(memberField); classDeclaration.Members.Add(GetActiveRecordMemberCompositeKeyProperty(compositeClass, memberField, cls.DoesImplementINotifyPropertyChanged(), cls.DoesImplementINotifyPropertyChanging())); } //ManyToOne links where this class is the target (1-n) ReadOnlyCollection<ManyToOneRelation> manyToOneSources = ManyToOneRelation.GetLinksToSources(cls); foreach (ManyToOneRelation relationship in manyToOneSources) { GenerateHasManyRelation(classDeclaration, nameSpace, relationship); } //ManyToOne links where this class is the source (n-1) ReadOnlyCollection<ManyToOneRelation> manyToOneTargets = ManyToOneRelation.GetLinksToTargets(cls); foreach (ManyToOneRelation relationship in manyToOneTargets) { GenerateBelongsToRelation(classDeclaration, nameSpace, relationship); } //ManyToMany links where this class is the source ReadOnlyCollection<ManyToManyRelation> manyToManyTargets = ManyToManyRelation.GetLinksToManyToManyTargets(cls); foreach (ManyToManyRelation relationship in manyToManyTargets) { GenerateHasAndBelongsToRelationFromTargets(classDeclaration, nameSpace, relationship); } //ManyToMany links where this class is the target ReadOnlyCollection<ManyToManyRelation> manyToManySources = ManyToManyRelation.GetLinksToManyToManySources(cls); foreach (ManyToManyRelation relationship in manyToManySources) { GenerateHasAndBelongsToRelationFromSources(classDeclaration, nameSpace, relationship); } //OneToOne link where this class is the source OneToOneRelation oneToOneTarget = OneToOneRelation.GetLinkToOneToOneTarget(cls); if (oneToOneTarget != null) { GenerateOneToOneRelationFromTarget(classDeclaration, nameSpace, oneToOneTarget); } //OneToOne links where this class is the target ReadOnlyCollection<OneToOneRelation> oneToOneSources = OneToOneRelation.GetLinksToOneToOneSources(cls); foreach (OneToOneRelation relationship in oneToOneSources) { GenerateOneToOneRelationFromSources(classDeclaration, nameSpace, relationship); } //Nested links ReadOnlyCollection<NestedClassReferencesModelClasses> nestingTargets = NestedClassReferencesModelClasses.GetLinksToNestedClasses(cls); foreach (NestedClassReferencesModelClasses relationship in nestingTargets) { GenerateNestingRelationFromRelationship(classDeclaration, relationship); } // TODO: Other relation types (any etc) GenerateDerivedClass(cls, nameSpace); templateMemberGenerator.AddTemplateMembers(cls, classDeclaration); return classDeclaration; }
private CodeTypeDeclaration GenerateNestedClass(NestedClass cls, CodeNamespace nameSpace) { if (cls == null) throw new ArgumentNullException( "cls", "Nested class not supplied"); if (nameSpace == null) throw new ArgumentNullException("nameSpace", "Namespace not supplied"); if (String.IsNullOrEmpty(cls.Name)) throw new ArgumentException("Class name cannot be blank", "cls"); CodeTypeDeclaration classDeclaration = GetNestedClassDeclaration(cls, nameSpace); // Properties and Fields foreach (var property in cls.Properties) { PropertyData propertyData = new PropertyData(property); AddMemberField(classDeclaration, propertyData); if (propertyData.DebuggerDisplay) classDeclaration.CustomAttributes.Add(propertyData.GetDebuggerDisplayAttribute()); if (propertyData.DefaultMember) classDeclaration.CustomAttributes.Add(propertyData.GetDefaultMemberAttribute()); } return classDeclaration; }