/// <summary>
        /// Generates the business logic class type.  We override this to control the base class and imports
        /// </summary>
        /// <param name="codeGenContext">The context to use to generate code.</param>
        /// <param name="codeNamespace">The namespace into which to generate code.</param>
        /// <param name="className">The name to use for the class.</param>
        /// <returns>The new type</returns>
        protected override CodeTypeDeclaration CreateBusinessLogicClass(ICodeGenContext codeGenContext, CodeNamespace codeNamespace, string className)
        {
            // Add an import for our domain service
            foreach (string import in BusinessLogicClassConstants.LinqToEntitiesDbImports)
            {
                codeNamespace.Imports.Add(new CodeNamespaceImport(import));
            }

            // Add an import for the namespace of the DomainContext
            if (this.ContextType.Namespace != codeNamespace.Name)
            {
                codeNamespace.Imports.Add(new CodeNamespaceImport(BusinessLogicClassConstants.DbContextNamespace));
                codeNamespace.Imports.Add(new CodeNamespaceImport(this.ContextType.Namespace));
            }

            // Add to the set of known references
            codeGenContext.AddReference(typeof(EntityState).Assembly.FullName);

            // We used to add OpenRiaServices.DomainServices.EntityFramework, but due to
            // vstfdevdiv/DevDiv2 Bug 442272 - Domain Service Wizard failing when an EF DbContext is selected,
            // we need to avoid doing that.

            if (DbContextUtilities.DbContextTypeReference != null)
            {
                codeGenContext.AddReference(DbContextUtilities.DbContextTypeReference.Assembly.FullName);
            }

            CodeTypeDeclaration businessLogicClass = CodeGenUtilities.CreateTypeDeclaration(className, codeNamespace.Name);
            CodeTypeReference   baseClass          = new CodeTypeReference(BusinessLogicClassConstants.DbDomainServiceTypeName, new CodeTypeReference(this.ContextType.Name));

            businessLogicClass.BaseTypes.Add(baseClass);
            return(businessLogicClass);
        }
Esempio n. 2
0
        /// <summary>
        /// Creates the entire business logic class in the specified namespace
        /// </summary>
        /// <param name="codeGenContext">The context into which to generate code.  It cannot be null.</param>
        /// <param name="codeNamespace">The namespace object into which the type should be defined.</param>
        /// <param name="className">The name of the class.  It cannot be null.</param>
        /// <returns>A new CodeTypeDeclaration for the generated class.</returns>
        protected virtual CodeTypeDeclaration CreateBusinessLogicClass(ICodeGenContext codeGenContext, CodeNamespace codeNamespace, string className)
        {
            CodeTypeDeclaration businessLogicClass = CodeGenUtilities.CreateTypeDeclaration(className, codeNamespace.Name);

            businessLogicClass.BaseTypes.Add(BusinessLogicClassConstants.DomainServiceTypeName);
            return(businessLogicClass);
        }
        /// <summary>
        /// Creates the business logic class.  Overridden to add imports, base class, etc.
        /// </summary>
        /// <param name="codeGenContext">The code gen context.></param>
        /// <param name="codeNamespace">The namespace name.</param>
        /// <param name="className">The class name.</param>
        /// <returns>the new type</returns>
        protected override CodeTypeDeclaration CreateBusinessLogicClass(CodeGenContext codeGenContext, CodeNamespace codeNamespace, string className)
        {
            Debug.Assert(LinqToSqlContext.linqToSqlDomainServiceAssemblyPath != null, "Unexpected method call when LinqToSqlDomainService assembly path has not been initialized!");

            if (LinqToSqlContext.linqToSqlDomainServiceAssemblyPath == null)
            {
                return(null);
            }

            // Add an import for our domain service
            foreach (string import in BusinessLogicClassConstants.LinqToSqlImports)
            {
                codeNamespace.Imports.Add(new CodeNamespaceImport(import));
            }

            // Add an import for the namespace of the DomainContext
            if (this.ContextType.Namespace != codeNamespace.Name)
            {
                codeNamespace.Imports.Add(new CodeNamespaceImport(this.ContextType.Namespace));
            }

            // Add to the set of known references
            codeGenContext.AddReference(typeof(DataContext).Assembly.FullName);
            codeGenContext.AddReference(LinqToSqlContext.linqToSqlDomainServiceAssemblyPath);

            CodeTypeDeclaration businessLogicClass = CodeGenUtilities.CreateTypeDeclaration(className, codeNamespace.Name);
            CodeTypeReference   baseClass          = new CodeTypeReference(BusinessLogicClassConstants.LinqToSqlDomainServiceTypeName, new CodeTypeReference(this.ContextType.Name));

            businessLogicClass.BaseTypes.Add(baseClass);
            return(businessLogicClass);
        }
Esempio n. 4
0
        /// <summary>
        /// Generates the business logic class type.  We override this to control the base class and imports
        /// </summary>
        /// <param name="codeGenContext">The context to use to generate code.</param>
        /// <param name="codeNamespace">The namespace into which to generate code.</param>
        /// <param name="className">The name to use for the class.</param>
        /// <returns>The new type</returns>
        protected override CodeTypeDeclaration CreateBusinessLogicClass(CodeGenContext codeGenContext, CodeNamespace codeNamespace, string className)
        {
            // Add an import for our domain service
            foreach (string import in BusinessLogicClassConstants.LinqToEntitiesImports)
            {
                codeNamespace.Imports.Add(new CodeNamespaceImport(import));
            }

            // Add an import for the namespace of the DomainContext
            if (this.ContextType.Namespace != codeNamespace.Name)
            {
                codeNamespace.Imports.Add(new CodeNamespaceImport(this.ContextType.Namespace));
            }

            // Add to the set of known references
            codeGenContext.AddReference(typeof(ObjectContext).Assembly.FullName);
            codeGenContext.AddReference(typeof(LinqToEntitiesDomainService <>).Assembly.FullName);

            CodeTypeDeclaration businessLogicClass = CodeGenUtilities.CreateTypeDeclaration(className, codeNamespace.Name);
            CodeTypeReference   baseClass          = new CodeTypeReference(BusinessLogicClassConstants.LinqToEntitiesDomainServiceTypeName, new CodeTypeReference(this.ContextType.Name));

            businessLogicClass.BaseTypes.Add(baseClass);
            return(businessLogicClass);
        }
Esempio n. 5
0
        /// <summary>
        /// Generates the metadata class for the given object (entity or complex object)
        /// </summary>
        /// <param name="codeGenContext">The context to use to generate code.</param>
        /// <param name="optionalSuffix">If not null, optional suffix to class name and namespace</param>
        /// <param name="type">The type of the object for which to generate the metadata class.</param>
        /// <returns><c>true</c> means at least some code was generated.</returns>
        public bool GenerateMetadataClass(ICodeGenContext codeGenContext, string optionalSuffix, Type type)
        {
            // If already have a buddy class, bypass all this logic
            // Use soft dependency (string name) to avoid static dependency on DataAnnotations.
            // We do this because this wizard must run from the GAC, and DataAnnotations will not necessarily be in the GAC too.
            Type buddyClassType = TypeUtilities.GetAssociatedMetadataType(type);

            if (buddyClassType != null)
            {
                return(false);
            }

            string className      = type.Name;
            string classNamespace = type.Namespace;

            bool addSuffix = !string.IsNullOrEmpty(optionalSuffix);

            if (addSuffix)
            {
                className      += optionalSuffix;
                classNamespace += optionalSuffix;
            }

            // Every object could have a unique namespace (odd, but true)
            // So we logically create a new namespace for each object.  Those
            // sharing a namespace will reuse the CodeNamespace.
            // We allow the caller to specify in case it needs to override that
            // namespace.  Unit testing is such a scenario
            CodeNamespace codeNamespace = codeGenContext.GetOrGenNamespace(classNamespace);

            // If we redirected to a different namespace than the object, import the real object's namespace
            if (addSuffix)
            {
                CodeGenUtilities.AddImportIfNeeded(codeNamespace, type.Namespace);
            }

            // Name of buddy class is $objectClassName$Metadata (e.g. Orders --> OrdersMetadata)
            string buddyClassName = className + "Metadata";

            // We use the full outer.inner type naming convention for VB because they cannot resolve it otherwise.
            // C# can currently resolve it due to a bug in the compiler, but it is safer to use the legal syntax here.
            string fullBuddyClassName = className + "." + buddyClassName;

            CodeTypeDeclaration objectClass = null;

            // public class $objectType$ { }
            objectClass                = CodeGenUtilities.CreateTypeDeclaration(className, classNamespace);
            objectClass.IsPartial      = true;
            objectClass.TypeAttributes = TypeAttributes.Public;

            // Add explanatory comments about what the [MetadataTypeAttribute] does
            objectClass.Comments.Add(new CodeCommentStatement(String.Format(CultureInfo.CurrentCulture, Resources.BusinessLogicClass_Entity_Partial_Class_Remarks, buddyClassName, className), false));

            // [MetadataType(typeof($objectType$.$objectType$_Metadata))]
            CodeAttributeDeclaration attr = CodeGenUtilities.CreateAttributeDeclaration(BusinessLogicClassConstants.MetadataTypeAttributeTypeName);

            CodeAttributeArgument attrArg = new CodeAttributeArgument(new CodeTypeOfExpression(fullBuddyClassName));

            attr.Arguments.Add(attrArg);
            objectClass.CustomAttributes.Add(attr);

            // public sealed class $objectType$_Metadata { }
            // (note: cannot set 'static' modified from CodeDom.)
            CodeTypeDeclaration buddyClass = CodeGenUtilities.CreateTypeDeclaration(buddyClassName, classNamespace);

            // Both VB and C# use a friend/public buddy class.  A private buddy class does not
            // compile in VB, and it compiles in C# only due to a bug.
            buddyClass.TypeAttributes = TypeAttributes.Sealed | TypeAttributes.NestedAssembly;
            bool generatedProperty = false;

            // Generate a developer comment describing what this class does
            buddyClass.Comments.Add(new CodeCommentStatement(String.Format(CultureInfo.CurrentCulture, Resources.Buddy_Class_Remarks, type.Name)));

            // Add a language-specific example
            string explanation = codeGenContext.IsCSharp ? Resources.Buddy_Class_Remarks_CSharp : Resources.Buddy_Class_Remarks_VB;

            buddyClass.Comments.Add(new CodeCommentStatement(explanation, false));

            // Generate a private ctor to make it impossible to instantiate this class
            CodeConstructor ctor = new CodeConstructor();

            ctor.Attributes = MemberAttributes.Private;
            ctor.Comments.Add(new CodeCommentStatement(Resources.BusinessLogicClass_Private_Ctor_Comment));
            buddyClass.Members.Add(ctor);

            // Sort by name order for baseline predictability
            foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).OrderBy(p => p.Name))
            {
                // CodeDom does not support auto-implemented properties, so we will generate fields and then transform them into properties
                Type propType = propertyInfo.PropertyType;
                if (propType.IsVisible && propertyInfo.GetGetMethod() != null && this.CanGeneratePropertyOfType(propType))
                {
                    // Add an import for this property type's namespace if needed
                    CodeGenUtilities.AddImportIfNeeded(codeNamespace, propertyInfo.PropertyType.Namespace);

                    CodeSnippetTypeMember property = CodeGenUtilities.CreateAutomaticPropertyDeclaration(codeGenContext, buddyClass, propertyInfo, !string.IsNullOrEmpty(codeNamespace.Name) /* insideNamespace */);

                    buddyClass.Members.Add(property);
                    generatedProperty = true;
                }
            }

            // Don't generate anything if the buddy class is empty
            if (generatedProperty)
            {
                // Add the partial object class to the namespace
                codeNamespace.Types.Add(objectClass);

                // Add the metadata class as a nested class inside the partial object class
                objectClass.Members.Add(buddyClass);
            }

            // false if no properties were generated, indicating no code should be emitted
            return(generatedProperty);
        }