/// <summary>
        /// Generates client proxy source code using the specified <paramref name="codeGeneratorName"/> in the context
        /// of the specified <paramref name="host"/>.
        /// </summary>
        /// <param name="host">The host for code generation.</param>
        /// <param name="options">The options to use for code generation.</param>
        /// <param name="assembliesToLoad">The set of server assemblies to use for analysis and composition.</param>
        /// <param name="codeGeneratorName">Optional generator name.  A <c>null</c> or empty value will select the default generator.</param>
        /// <returns>The generated source code or <c>null</c> if none was generated.</returns>
        public string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable <string> assembliesToLoad, string codeGeneratorName)
        {
            Debug.Assert(host != null, "host cannot be null");
            Debug.Assert(options != null, "options cannot be null");
            Debug.Assert(assembliesToLoad != null, "assembliesToLoad cannot be null");

            var logger  = host as ILogger;
            var catalog = new EntityCatalog(assembliesToLoad, logger);

            return(this.GenerateCode(host, options, catalog, assembliesToLoad, codeGeneratorName));
        }
        /// <summary>
        /// Generates client proxy source code using the specified <paramref name="codeGeneratorName"/> in the context
        /// of the specified <paramref name="host"/>.
        /// </summary>
        /// <param name="host">The host for code generation.</param>
        /// <param name="options">The options to use for code generation.</param>
        /// <param name="entityTypes">The set of <see cref="Luma.Client.Entity"/> types for which to generate code.</param>
        /// <param name="compositionAssemblies">The optional set of assemblies to use to create the MEF composition container.</param>
        /// <param name="codeGeneratorName">Optional generator name.  A <c>null</c> or empty value will select the default generator.</param>
        /// <returns>The generated source code or <c>null</c> if none was generated.</returns>
        public string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable <Type> entityTypes, IEnumerable <string> compositionAssemblies, string codeGeneratorName)
        {
            Debug.Assert(host != null, "host cannot be null");
            Debug.Assert(options != null, "options cannot be null");
            Debug.Assert(entityTypes != null, "entityTypes cannot be null");

            ILogger logger  = host as ILogger;
            var     catalog = new EntityCatalog(entityTypes, logger);

            return(this.GenerateCode(host, options, catalog, compositionAssemblies, codeGeneratorName));
        }
        /// <summary>
        /// Generates client proxy source code using the specified <paramref name="codeGeneratorName"/> in the context
        /// of the specified <paramref name="host"/>.
        /// </summary>
        /// <param name="host">The host for code generation.</param>
        /// <param name="options">The options to use for code generation.</param>
        /// <param name="catalog">The catalog containing the <see cref="Luma.Client.Entity"/> types.</param>
        /// <param name="compositionAssemblies">The optional set of assemblies to use to create the MEF composition container.</param>
        /// <param name="codeGeneratorName">Optional generator name.  A <c>null</c> or empty value will select the default generator.</param>
        /// <returns>The generated source code or <c>null</c> if none was generated.</returns>
        public string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, EntityCatalog catalog, IEnumerable <string> compositionAssemblies, string codeGeneratorName)
        {
            Debug.Assert(host != null, "host cannot be null");
            Debug.Assert(options != null, "options cannot be null");
            Debug.Assert(catalog != null, "catalog cannot be null");

            IEnumerable <EntityDescription> entityDescriptions = catalog.EntityDescriptions;
            IClientCodeGenerator            proxyGenerator     = FindCodeGenerator(host, options, compositionAssemblies, codeGeneratorName);
            string generatedCode = null;

            if (proxyGenerator != null)
            {
                try
                {
                    generatedCode = proxyGenerator.GenerateCode(host, entityDescriptions, options);
                }
                catch (Exception ex)
                {
                    // Fatal exceptions are never swallowed or processed
                    if (ex.IsFatal())
                    {
                        throw;
                    }

                    // Any exception from the code generator is caught and reported, otherwise it will
                    // hit the MSBuild backstop and report failure of the custom build task.
                    // It is acceptable to report this exception and "ignore" it because we
                    // are running in a separate AppDomain which will be torn down immediately
                    // after our return.
                    host.LogError(string.Format(CultureInfo.CurrentCulture,
                                                Resource.CodeGenerator_Threw_Exception,
                                                string.IsNullOrEmpty(codeGeneratorName) ? proxyGenerator.GetType().FullName : codeGeneratorName,
                                                options.ClientProjectPath,
                                                ex.Message));
                }
            }

            return(generatedCode);
        }