/// <summary> /// Retrieves the set of <see cref="EntityData"/> data objects for all the entities /// belonging to the specified context. /// </summary> /// <remarks> /// The primary purpose of this method is lazy loading. The view model will ask for /// these only when it needs them. It allows us to defer examining metadata until /// we absolutely need it, which could be a large performance win when multiple /// contexts are available. /// </remarks> /// <param name="contextData">The <see cref="ContextData"/> to use to locate /// the respective <see cref="BusinessLogicContext"/>.</param> /// <returns>The set of <see cref="EntityData"/> objects for the given context.</returns> public EntityData[] GetEntityDataItemsForContext(ContextData contextData) { BusinessLogicContext context = this._contexts[contextData.ID]; List <BusinessLogicEntity> entities = (context == null) ? new List <BusinessLogicEntity>() : context.Entities.ToList(); return(entities.Select <BusinessLogicEntity, EntityData>(ble => ble.EntityData).ToArray()); }
public bool IsMetadataGenerationRequired(ContextData contextData) { BusinessLogicContext context = this._contexts.SingleOrDefault(c => c.ContextData.ID == contextData.ID); return((context) != null ? context.NeedToGenerateMetadataClasses : false); }
/// <summary> /// Generates the source code for the metadata class for the given context. /// </summary> /// <param name="contextData">The <see cref="ContextData"/> to use to locate the appropriate <see cref="BusinessLogicContext"/>.</param> /// <param name="rootNamespace">The root namespace (VB).</param> /// <param name="optionalSuffix">If nonblank, the suffix to append to namespace and class names for testing</param> /// <returns>A value containing the generated source code and necessary references.</returns> public GeneratedCode GenerateMetadataClasses(ContextData contextData, string rootNamespace, string optionalSuffix) { BusinessLogicContext context = this._contexts.Single(c => c.ContextData.ID == contextData.ID); return((context) != null ? context.GenerateMetadataClasses(this.Language, rootNamespace, optionalSuffix) : new GeneratedCode(string.Empty, new string[0])); }
/// <summary> /// Generates source code for the specified context. /// </summary> /// <param name="contextData">The <see cref="ContextData"/> to use to locate the appropriate <see cref="BusinessLogicContext"/>.</param> /// <param name="className">The name of the class.</param> /// <param name="namespaceName">The namespace to use for the class.</param> /// <param name="rootNamespace">The root namespace (VB).</param> /// <returns>A value containing the generated source code and necessary references.</returns> public GeneratedCode GenerateBusinessLogicClass(ContextData contextData, string className, string namespaceName, string rootNamespace) { BusinessLogicContext context = this._contexts.SingleOrDefault(c => c.ContextData.ID == contextData.ID); return(context != null ? context.GenerateBusinessLogicClass(this.Language, className, namespaceName, rootNamespace) : new GeneratedCode()); }
/// <summary> /// Tests whether we need to generate the GetEntityState helper method. We do for POCO types. /// If we determine we need to generate that helper, this method generates it and adds it to /// the list of helper methods that will be appended to the generated code. /// </summary> /// <param name="codeGenContext">The context in which we are generating code.</param> /// <param name="businessLogicClass">The class containing the generated code.</param> /// <param name="entity">The entity that we need to test to determine whether the helper is needed.</param> /// <returns><c>true</c> means the helper should be used.</returns> private static bool GenerateGetEntityStateIfNecessary(CodeGenContext codeGenContext, CodeTypeDeclaration businessLogicClass, BusinessLogicEntity entity) { if (typeof(EntityObject).IsAssignableFrom(entity.ClrType)) { return(false); } BusinessLogicContext.GenerateHelperMemberIfNecessary(codeGenContext, businessLogicClass, LinqToEntitiesContext.GetEntityStateHelperMethodName, () => { return(LinqToEntitiesContext.GenerateGetEntityState(codeGenContext, businessLogicClass)); }); return(true); }
/// <summary> /// Tests whether the specified helper member has been generated, and if not, invokes /// a callback to generate it. /// </summary> /// <param name="codeGenContext">The context in which we are generating code.</param> /// <param name="businessLogicClass">The class containing the generated code.</param> /// <param name="helperMemberName">The name of the helper member.</param> /// <param name="generatorCallback">Callback that will create this helper if it does not yet exist.</param> public static void GenerateHelperMemberIfNecessary(ICodeGenContext codeGenContext, CodeTypeDeclaration businessLogicClass, string helperMemberName, Func <CodeTypeMember> generatorCallback) { System.Diagnostics.Debug.Assert(codeGenContext != null, "CodeGenContext cannot be null"); System.Diagnostics.Debug.Assert(businessLogicClass != null, "BusinessLogicClass cannot be null"); System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(helperMemberName), "Helper member name cannot be empty."); System.Diagnostics.Debug.Assert(generatorCallback != null, "callback cannot be null"); Dictionary <string, CodeTypeMember> memberDictionary = BusinessLogicContext.GetHelperMemberDictionary(businessLogicClass); if (!memberDictionary.ContainsKey(helperMemberName)) { CodeTypeMember member = generatorCallback(); if (member != null) { memberDictionary[helperMemberName] = member; } } }
/// <summary> /// Creates the entire business logic class within the specified namespace name /// </summary> /// <param name="codeGenContext">The context into which to generate code. It cannot be null.</param> /// <param name="className">The name of the class to generate. It cannot be null or empty.</param> /// <param name="namespaceName">The namespace to use for the generated code. It cannot be empty.</param> protected void GenerateBusinessLogicClass(CodeGenContext codeGenContext, string className, string namespaceName) { if (codeGenContext == null) { throw new ArgumentNullException("codeGenContext"); } if (string.IsNullOrEmpty(className)) { throw new ArgumentNullException("className"); } if (string.IsNullOrEmpty(namespaceName)) { throw new ArgumentNullException("namespaceName"); } // namespace XXX { } CodeNamespace ns = codeGenContext.GetOrGenNamespace(namespaceName); // public class $classname$ { } CodeTypeDeclaration businessLogicClass = this.CreateBusinessLogicClass(codeGenContext, ns, className); ns.Types.Add(businessLogicClass); // Class-level Xml comments // Empty class gets its own comment because it has no ContextType to describe string remarksComment; if (this.ContextType == null) { remarksComment = Resources.BusinessLogicClass_Class_Remarks_Empty; } else { remarksComment = String.Format(CultureInfo.CurrentCulture, Resources.BusinessLogicClass_Class_Remarks, this.ContextType.Name); } // Add developer comment explaining what this class does businessLogicClass.Comments.Add(new CodeCommentStatement(remarksComment, false)); // Add [RequiresAuthentication] as a comment if (this.ContextType != null) { remarksComment = codeGenContext.IsCSharp ? Resources.BusinessLogicClass_RequiresAuthentication_CSharp : Resources.BusinessLogicClass_RequiresAuthentication_VB; businessLogicClass.Comments.Add(new CodeCommentStatement(remarksComment, false)); } if (this.IsClientAccessEnabled) { // [EnableClientAccess] CodeAttributeDeclaration attr = CodeGenUtilities.CreateAttributeDeclaration(BusinessLogicClassConstants.EnableClientAccessAttributeTypeName); businessLogicClass.CustomAttributes.Add(attr); } else { // if not enabled, add a comment explaining how to enable it businessLogicClass.Comments.Add(new CodeCommentStatement(Resources.BusinessLogicClass_EnableClientAccess_Comment)); } // Gen all domain operation entries // Sort by name for baseline predictability foreach (BusinessLogicEntity entity in this.Entities.OrderBy(e => e.Name)) { if (entity.IsIncluded) { // Add an import for this entity's namespace if needed // This is necessary only when entities exist in a different namespace from the context CodeGenUtilities.AddImportIfNeeded(ns, entity.ClrType.Namespace); this.GenerateEntityDomainOperationEntries(codeGenContext, businessLogicClass, entity); } } // If any private helper methods were generated, append them now. // We sort by their keys to give baseline predictability. Dictionary <string, CodeTypeMember> helpers = BusinessLogicContext.GetHelperMemberDictionary(businessLogicClass); foreach (string key in helpers.Keys.OrderBy(s => s)) { businessLogicClass.Members.Add(helpers[key]); } // If we exposed an OData endpoint, add a reference to the OData assembly // so it appears in the server project, allowing the user to chose // CopyLocal=true for bin deploy scenarios if (this.IsODataEndpointEnabled) { codeGenContext.AddReference(typeof(ODataEndpointFactory).Assembly.FullName); } }
/// <summary> /// Initializes a new instance of the <see cref="BusinessLogicEntity"/> class. /// </summary> /// <param name="businessLogicContext">The context that owns this entity. It cannot be null.</param> /// <param name="name">The name of the entity as it will appear in the UI</param> /// <param name="type">The CLR type of the entity as it will be used in code gen</param> public BusinessLogicEntity(BusinessLogicContext businessLogicContext, string name, Type type) { this._businessLogicContext = businessLogicContext; this._name = name; this._type = type; }