/// <summary> /// Creates a backing field for the given property /// </summary> /// <param name="property">The code property</param> /// <param name="type">The type of the property</param> /// <param name="initialValue">The initial value expression for the field</param> /// <returns>A reference to the generated backing field</returns> public static CodeFieldReferenceExpression CreateBackingField(this CodeMemberProperty property, CodeTypeReference type, CodeExpression initialValue) { var reference = CodeDomHelper.GetOrCreateUserItem <CodeFieldReferenceExpression>(property, CodeDomHelper.BackingFieldKey); if (reference == null) { var field = new CodeMemberField() { Attributes = MemberAttributes.Private, Name = "_" + property.Name.ToCamelCase(), Type = type ?? new CodeTypeReference(typeof(object)) }; field.WriteDocumentation(string.Format("The backing field for the {0} property", property.Name)); property.DependentMembers(true).Add(field); if (initialValue != null) { field.InitExpression = initialValue; } reference = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), field.Name); CodeDomHelper.SetUserItem(property, CodeDomHelper.BackingFieldRefKey, reference); CodeDomHelper.SetUserItem(property, CodeDomHelper.BackingFieldKey, field); } return(reference); }
/// <summary> /// Creates a dependency to generate the code for the base classes of the current class /// </summary> /// <typeparam name="TClass">The model element type from which to generate the base class</typeparam> /// <param name="rule">The transformation rule that is used to generate the class</param> /// <param name="selector">A function used to select the model element from which to generate a base class</param> /// <returns>The transformation rule dependency</returns> public ITransformationRuleDependency RequireBaseClass <TClass>(TransformationRuleBase <TClass, CodeTypeDeclaration> rule, Func <T, TClass> selector) where TClass : class { return(Require(rule, selector, (cl, baseClass) => { var typeRef = CodeDomHelper.GetOrCreateUserItem <CodeTypeReference>(baseClass, CodeDomHelper.TypeReferenceKey, () => new CodeTypeReference()); cl.BaseTypes.Add(typeRef); })); }
protected virtual void ResolveMultipleInheritanceMembers(CodeTypeDeclaration generatedType, HashSet <CodeTypeMember> shadows, CodeConstructor constructor) { Func <CodeTypeDeclaration, IEnumerable <CodeTypeDeclaration> > getBaseTypes = type => { var interfaceType = CodeDomHelper.GetOrCreateUserItem <CodeTypeDeclaration>(type, CodeDomHelper.InterfaceKey); if (interfaceType == null) { interfaceType = type; } return(interfaceType.BaseTypes.Cast <CodeTypeReference>().Select(r => r.GetTypeForReference()).Where(c => c != null)); }; var layering = Layering <CodeTypeDeclaration> .CreateLayers(generatedType, getBaseTypes); CodeTypeDeclaration implBaseType = FindBaseClassAndCreateShadows(generatedType, shadows, layering); IEnumerable <CodeTypeDeclaration> inheritedBaseClasses; if (implBaseType != null) { inheritedBaseClasses = implBaseType.Closure(getBaseTypes); var implementationRef = new CodeTypeReference(); implementationRef.BaseType = implBaseType.Name; var n = implBaseType.GetReferenceForType().Namespace(); if (n != null && n.EndsWith(implBaseType.Name)) { implementationRef.BaseType = n + "." + implBaseType.Name; } else { implementationRef.SetNamespace(n); } generatedType.BaseTypes.Insert(0, implementationRef); } else { inheritedBaseClasses = Enumerable.Empty <CodeTypeDeclaration>(); AddImplementationBaseClass(generatedType); } for (int i = layering.Count - 1; i >= 0; i--) { foreach (var baseType in layering[i]) { if (!inheritedBaseClasses.Contains(baseType) && baseType != generatedType && ShouldContainMembers(generatedType, baseType.GetReferenceForType())) { var dependent = baseType.DependentMembers(false); if (dependent != null) { foreach (var inheritedMember in dependent) { RecursivelyAddDependentMembers(generatedType.Members, constructor.Statements, inheritedMember, shadows); } } } } } }
private static IEnumerable <CodeTypeDeclaration> GetBaseClasses(CodeTypeDeclaration type) { var interfaceType = CodeDomHelper.GetOrCreateUserItem <CodeTypeDeclaration>(type, CodeDomHelper.InterfaceKey); if (interfaceType == null) { interfaceType = type; } return(interfaceType.BaseTypes.Cast <CodeTypeReference>().Select(r => r.GetTypeForReference()).Where(c => c != null)); }
protected virtual bool ShouldContainMembers(CodeTypeDeclaration generatedType, CodeTypeDeclaration baseType) { var baseClasses = CodeDomHelper.GetOrCreateUserItem <IEnumerable <CodeTypeDeclaration> >(generatedType, CodeDomHelper.BaseClassesKey); if (baseClasses == null) { return(true); } else { return(!baseClasses.Contains(baseType)); } }
/// <summary> /// Initializes the generated type declaration /// </summary> /// <param name="input">The input model element</param> /// <param name="generatedType">The generated class declaration</param> /// <param name="context">The transformation context</param> /// <remarks>Can be overridden to refine code generation</remarks> public override void Transform(T input, CodeTypeDeclaration generatedType, ITransformationContext context) { HashSet <CodeTypeMember> shadows; var ownShadows = generatedType.Shadows(false); if (ownShadows != null) { shadows = new HashSet <CodeTypeMember>(ownShadows); } else { shadows = new HashSet <CodeTypeMember>(); } var constructor = CodeDomHelper.GetOrCreateDefaultConstructor(generatedType, () => new CodeConstructor() { Attributes = MemberAttributes.Public }); var dependends = generatedType.DependentMembers(false); if (dependends != null) { foreach (var member in dependends) { RecursivelyAddDependentMembers(generatedType.Members, constructor.Statements, member, shadows); } } var interfaceDecl = CreateSeparatePublicInterface(input, generatedType); if (interfaceDecl != null) { CodeDomHelper.SetUserItem(generatedType, CodeDomHelper.InterfaceKey, interfaceDecl); var dependentTypes = CodeDomHelper.DependentTypes(generatedType, true); dependentTypes.Add(interfaceDecl); var typeReference = generatedType.GetReferenceForType(); typeReference.BaseType = interfaceDecl.Name; CreateInterfaceMembers(generatedType, interfaceDecl); for (int i = generatedType.BaseTypes.Count - 1; i >= 0; i--) { var baseTypeRef = generatedType.BaseTypes[i]; var baseType = CodeDomHelper.GetOrCreateUserItem <CodeTypeDeclaration>(baseTypeRef, CodeDomHelper.ClassKey); if (baseType == null) { continue; } interfaceDecl.BaseTypes.Add(baseTypeRef); generatedType.BaseTypes.RemoveAt(i); } generatedType.BaseTypes.Add(typeReference); ResolveMultipleInheritanceMembers(generatedType, shadows, constructor); } if (constructor.Statements.Count > 0) { CodeDomHelper.SetUserItem(generatedType, CodeDomHelper.ConstructorKey, constructor); generatedType.Members.Add(constructor); } }