/// <summary> /// Generates an interface for each template that the current template derives from, recursively. /// </summary> private void GenerateInterfaceCode(CodeCompileUnit interfaceUnit) { foreach (var template in _metadata.Interfaces) { CodeNamespace interfaceNamespace = GetNamespaceWithCreate(interfaceUnit, template.Namespace); CodeTypeDeclaration interfaceType = interfaceNamespace.CreateType(MemberAttributes.Public, template.TypeName); interfaceType.IsInterface = true; interfaceType.IsPartial = true; AddGeneratedCodeAttributeToType(interfaceType); AddVersionAttributeToInterface(interfaceType, template.Template); // adds version data to the interface (for synchronization purposes) AddCommentsToItem(interfaceType, template.Template); // add XML comments based on Sitecore Help content // generate interface properties foreach (var field in template.FieldsToGenerate) { CreateInterfaceProperty(field, interfaceType.Members); } // add base interface inheritance foreach (var baseTemplate in template.InterfacesImplemented) { interfaceType.BaseTypes.Add(new CodeTypeReference(baseTemplate.TypeFullName, CodeTypeReferenceOptions.GlobalReference)); // assign interface implementation } // if this interface has no bases make sure we're deriving from the standard template if (interfaceType.BaseTypes.Count == 0 || (interfaceType.BaseTypes.Count == 1 && interfaceType.BaseTypes[0].BaseType.Contains(_parameters.ItemBaseInterface.FullName))) // any base types indicate it's inheriting from another sitecore interface - and we don't want to dupe the base class fields twice { interfaceType.BaseTypes.Add(new CodeTypeReference(_parameters.ItemBaseInterface)); } } }
/// <summary> /// Generates code representing a set of Sitecore templates /// </summary> private void GenerateTemplateCode(CodeCompileUnit concreteUnit) { foreach (var template in _metadata.Templates) { // setup concrete model object CodeNamespace templateNamespace = GetNamespaceWithCreate(concreteUnit, template.Namespace); CodeTypeDeclaration concrete = templateNamespace.CreateType(MemberAttributes.Public, template.TypeName.AsIdentifier()); concrete.IsClass = true; concrete.IsPartial = true; concrete.BaseTypes.Add(new CodeTypeReference(_parameters.ItemBaseClass, CodeTypeReferenceOptions.GlobalReference)); // add the constructor (validates item template) concrete.Members.AddRange(CreateItemConstructors()); AddGeneratedCodeAttributeToType(concrete); AddTemplateIdPropertiesToEntity(concrete, template.Template); // adds static and dynamic template ID property AddCommentsToItem(concrete, template.Template); // adds XML comments based on Sitecore Help fields // generate item properties foreach (var field in template.FieldsToGenerate) { CreateItemProperty(field, concrete.Members); } // generates interfaces to represent the Sitecore template inheritance hierarchy foreach (var baseType in template.InterfacesImplemented) { concrete.BaseTypes.Add(new CodeTypeReference(baseType.TypeFullName, CodeTypeReferenceOptions.GlobalReference)); // implement the base type interface } // create initializer class CreateInitializer(templateNamespace, concrete, template.Template.TemplateId); } }
/// <summary> /// Generates an Initializer class (a proxy that allows us to quickly construct instances of a strongly typed item wrapper without resorting to reflection) /// </summary> private void CreateInitializer(CodeNamespace templateNamespace, CodeTypeDeclaration concrete, ID templateId) { CodeTypeDeclaration initializer = templateNamespace.CreateType(MemberAttributes.Public, concrete.Name + "Initializer"); // ReSharper disable BitwiseOperatorOnEnumWithoutFlags initializer.Attributes = MemberAttributes.Public | MemberAttributes.Final; // ReSharper restore BitwiseOperatorOnEnumWithoutFlags initializer.BaseTypes.Add(typeof(ITemplateInitializer)); AddGeneratedCodeAttributeToType(initializer); var templateIdProperty = new CodeMemberProperty { // ReSharper disable BitwiseOperatorOnEnumWithoutFlags Attributes = MemberAttributes.Public | MemberAttributes.Final, // ReSharper restore BitwiseOperatorOnEnumWithoutFlags Type = new CodeTypeReference(typeof(ID)), Name = "InitializesTemplateId" }; // all this for return new ID("xxxxx"); lol templateIdProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodeObjectCreateExpression(typeof(ID), new CodeSnippetExpression("\"" + templateId + "\"")))); initializer.Members.Add(templateIdProperty); var initializerItemMethod = new CodeMemberMethod { Name = "CreateInstance", // ReSharper disable BitwiseOperatorOnEnumWithoutFlags Attributes = MemberAttributes.Public | MemberAttributes.Final, // ReSharper restore BitwiseOperatorOnEnumWithoutFlags ReturnType = new CodeTypeReference(typeof(IStandardTemplateItem)) }; initializerItemMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(Item), "innerItem")); // all this for return new ConcreteType(innerItem); lol initializerItemMethod.Statements.Add(new CodeMethodReturnStatement(new CodeObjectCreateExpression(new CodeTypeReference(concrete.Name), new CodeVariableReferenceExpression("innerItem")))); initializer.Members.Add(initializerItemMethod); var initializerIndexMethod = new CodeMemberMethod { Name = "CreateInstanceFromSearch", // ReSharper disable BitwiseOperatorOnEnumWithoutFlags Attributes = MemberAttributes.Public | MemberAttributes.Final, // ReSharper restore BitwiseOperatorOnEnumWithoutFlags ReturnType = new CodeTypeReference(typeof(IStandardTemplateItem)) }; initializerIndexMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(IDictionary <string, string>), CodeTypeReferenceOptions.GlobalReference), "searchFields")); // all this for return new ConcreteType(searchFields); lol initializerIndexMethod.Statements.Add(new CodeMethodReturnStatement(new CodeObjectCreateExpression(new CodeTypeReference(concrete.Name), new CodeVariableReferenceExpression("searchFields")))); initializer.Members.Add(initializerIndexMethod); }
/// <summary> /// Generates code representing a set of Sitecore templates /// </summary> private void GenerateTemplateCode(CodeCompileUnit concreteUnit, CodeCompileUnit interfaceUnit) { CodeNamespace interfaceNamespace = interfaceUnit.CreateNamespace(Parameters.InterfaceNamespace); var templatesToGenerate = new List <TemplateGenerationInfo>(Templates); // as interface generation can modify the Templates collection, we need to make an immutable copy of the collection items before we iterate over it foreach (var template in templatesToGenerate) { // setup concrete model object CodeNamespace templateNamespace = GetTemplateNamespace(concreteUnit, template.Template.ID, Parameters.ItemNamespace); CodeTypeDeclaration concrete = templateNamespace.CreateType(MemberAttributes.Public, template.TypeName); concrete.IsClass = true; concrete.IsPartial = true; concrete.BaseTypes.Add(new CodeTypeReference(Parameters.ItemBaseClass, CodeTypeReferenceOptions.GlobalReference)); // add the constructor (validates item template) concrete.Members.AddRange(CreateItemConstructors()); AddGeneratedCodeAttributeToType(concrete); AddTemplateIdPropertiesToEntity(concrete, template.Template); // adds static and dynamic template ID property AddCommentsToItem(concrete, template.Template); // adds XML comments based on Sitecore Help fields HashSet <string> fieldKeys = GetBaseFieldSet(); fieldKeys.Add(concrete.Name.AsIdentifier()); // member names cannot be the same as their enclosing type so we add the type name to the fields collection foreach (var baseTemplate in template.AllNonstandardBaseTemplates) // similarly names can't be the same as any of their base templates' names (this would cause an incompletely implemented interface) { fieldKeys.Add(baseTemplate.Template.Name.AsIdentifier()); // NOTE: you could break this if you have a base template called Foo and a field called Foo that IS NOT on the Foo template (but why would you have that?) } // generate item properties foreach (var field in template.Template.Fields) { if (_templateInputProvider.IsFieldIncluded(field)) // query the template input provider and make sure we generate { string propertyName = field.Name.AsNovelIdentifier(fieldKeys); bool propertyAdded = CreateItemProperty(propertyName, field, concrete.Members); if (propertyAdded) { // record usage of the property name fieldKeys.Add(propertyName); } } } // generates interfaces to represent the Sitecore template inheritance hierarchy string baseInterface = GenerateInheritedInterfaces(template.Template, interfaceUnit, interfaceNamespace); if (!string.IsNullOrEmpty(baseInterface)) { concrete.BaseTypes.Add(new CodeTypeReference(baseInterface, CodeTypeReferenceOptions.GlobalReference)); // implement the base type interface } // create initializer class CreateInitializer(templateNamespace, concrete, template.Template.ID); } }