private CodeTypeDeclaration CreateFkClass(
IMap map,
IDictionary<Type, IMap> maps,
CodeGeneratorConfig codeGeneratorConfig) {
// generate the foreign key access class based on the original class
var foreignKeyClass =
new CodeTypeDeclaration(
map.Type.Name + codeGeneratorConfig.ForeignKeyAccessClassSuffix);
foreignKeyClass.IsClass = true;
foreignKeyClass.TypeAttributes = TypeAttributes.Public;
foreignKeyClass.BaseTypes.Add(map.Type);
foreach (
var column in
map.Columns.Where(c => c.Value.Relationship == RelationshipType.ManyToOne || c.Value.Relationship == RelationshipType.OneToOne)) {
if (!column.Value.Map.Type.GetProperty(column.Value.Name).GetGetMethod().IsVirtual
|| !column.Value.Map.Type.GetProperty(column.Value.Name).CanWrite) {
// TODO: send a warning back to the programmer, did they mean to do this?
continue;
}
// create a backing property for storing the FK
var backingType = column.Value.DbType.GetCLRType();
if (backingType.IsValueType) {
backingType = typeof(Nullable<>).MakeGenericType(backingType);
}
var foreignKeyBackingProperty = this.GenerateGetSetProperty(
foreignKeyClass,
column.Value.DbName,
backingType,
FinalPublic);
// create a backing field for storing the related entity
var backingField = new CodeMemberField(
column.Value.Type,
column.Value.Name + codeGeneratorConfig.ForeignKeyAccessEntityFieldSuffix);
foreignKeyClass.Members.Add(backingField);
// override the property getter and setter to use the backingfield
var property = new CodeMemberProperty();
property.Name = column.Value.Name;
property.Type = new CodeTypeReference(column.Value.Type);
property.Attributes = MemberAttributes.Public | MemberAttributes.Override;
property.GetStatements.Add(
new CodeConditionStatement(
//// if backingField != null or Fk backing field is null return
new CodeBinaryOperatorExpression(
CodeHelpers.ThisFieldIsNotNull(backingField.Name),
CodeBinaryOperatorType.BooleanOr,
CodeHelpers.ThisPropertyIsNull(foreignKeyBackingProperty.Name)),
new CodeStatement[] {
// true
new CodeMethodReturnStatement(
CodeHelpers.ThisField(backingField.Name))
},
new CodeStatement[] {
// false, return new object with foreign key set
new CodeVariableDeclarationStatement(
column.Value.Type,
"val",
new CodeObjectCreateExpression(
column.Value.Type)),
new CodeAssignStatement(
new CodeFieldReferenceExpression(
new CodeVariableReferenceExpression("val"),
maps[column.Value.Type].PrimaryKey.Name),
new CodePropertyReferenceExpression(
CodeHelpers.ThisProperty(
foreignKeyBackingProperty.Name),
"Value")),
new CodeAssignStatement(
CodeHelpers.ThisField(backingField.Name),
new CodeVariableReferenceExpression("val")),
new CodeMethodReturnStatement(
new CodeVariableReferenceExpression("val"))
}));
property.SetStatements.Add(
new CodeAssignStatement(
CodeHelpers.ThisField(backingField.Name),
new CodePropertySetValueReferenceExpression()));
foreignKeyClass.Members.Add(property);
}
return foreignKeyClass;
}