/// <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> internal 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"); ILogger logger = host as ILogger; DomainServiceCatalog catalog = new DomainServiceCatalog(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="domainServiceTypes">The set of <see cref="OpenRiaServices.DomainServices.Server.DomainService"/> 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> internal string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable <Type> domainServiceTypes, IEnumerable <string> compositionAssemblies, string codeGeneratorName) { Debug.Assert(host != null, "host cannot be null"); Debug.Assert(options != null, "options cannot be null"); Debug.Assert(domainServiceTypes != null, "domainServiceTypes cannot be null"); ILogger logger = host as ILogger; DomainServiceCatalog catalog = new DomainServiceCatalog(domainServiceTypes, 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="OpenRiaServices.DomainServices.Server.DomainService"/> 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> private string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, DomainServiceCatalog 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 <DomainServiceDescription> domainServiceDescriptions = catalog.DomainServiceDescriptions; IDomainServiceClientCodeGenerator proxyGenerator = this.FindCodeGenerator(host, options, compositionAssemblies, codeGeneratorName); string generatedCode = null; if (proxyGenerator != null) { try { generatedCode = proxyGenerator.GenerateCode(host, domainServiceDescriptions, 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); }
/// <summary> /// Validates code gen for a specific language by comparing it against a file containing the expected output. /// </summary> /// <param name="codeGenOptions">The options specifying the type of validation to perform</param> /// <returns>A command that updates the comparison file</returns> internal static string ValidateLanguageCodeGen(CodeGenValidationOptions codeGenOptions) { Assert.IsFalse(string.IsNullOrEmpty(codeGenOptions.Language)); string outDataDir = TestHelper.GetOutputTestDataDir(codeGenOptions.RelativeDeployDir); string extension = TestHelper.ExtensionFromLanguage(codeGenOptions.Language); string diffMessage = string.Empty; // Compose the abs path to where the test file got deployed by MSTest string referenceFileName = TestHelper.GetTestFileName(codeGenOptions.RelativeTestDir, codeGenOptions.BaseReferenceFileName + extension); Assert.IsTrue(File.Exists(referenceFileName), "Cannot find reference file " + referenceFileName); string generatedCode = string.Empty; ClientCodeGenerationOptions options = new ClientCodeGenerationOptions() { Language = codeGenOptions.Language, ClientRootNamespace = codeGenOptions.RootNamespace, ClientProjectPath = "MockProject.proj", IsApplicationContextGenerationEnabled = codeGenOptions.GenerateApplicationContexts, UseFullTypeNames = codeGenOptions.UseFullTypeNames, ClientProjectTargetPlatform = TargetPlatform.Silverlight }; MockCodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(codeGenOptions.Logger, codeGenOptions.SharedCodeService); ILogger logger = host as ILogger; DomainServiceCatalog catalog = new DomainServiceCatalog(codeGenOptions.DomainServiceTypes, logger); IDomainServiceClientCodeGenerator generator; using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { generator = dispatcher.FindCodeGenerator(host, options, /*compositionAssemblies*/ null, /*codeGeneratorName*/ null); } Assert.IsNotNull(generator, "Failed to find a code generator"); generatedCode = generator.GenerateCode(host, catalog.DomainServiceDescriptions, options); ConsoleLogger consoleLogger = logger as ConsoleLogger; string errors = consoleLogger == null ? "" : consoleLogger.Errors; Assert.IsTrue(generatedCode.Length > 0, "No code was generated: " + errors); // Dump the generated code into a file for comparison bool isCSharp = options.Language.Equals("C#", StringComparison.InvariantCultureIgnoreCase); string generatedFileName = Path.Combine(outDataDir, Path.GetFileName(referenceFileName) + ".testgen"); File.WriteAllText(generatedFileName, generatedCode); // TODO: (ron M3) Solve inability to get right MSBuild after checkin // First see if we compile List<string> referenceAssemblies = CompilerHelper.GetSilverlightClientAssemblies(codeGenOptions.RelativeDeployDir); List<string> files = new List<string>(); files.Add(generatedFileName); // Unconditionally force generation of Xml doc comments to catch errors string documentationFile = Path.GetTempFileName(); try { if (isCSharp) { files.AddRange(codeGenOptions.SharedFiles.Where(sharedFile => Path.GetExtension(sharedFile).Equals(".cs"))); CompilerHelper.CompileCSharpSource(files, referenceAssemblies, documentationFile); } else { files.AddRange(codeGenOptions.SharedFiles.Where(sharedFile => Path.GetExtension(sharedFile).Equals(".vb"))); CompilerHelper.CompileVisualBasicSource(files, referenceAssemblies, options.ClientRootNamespace, documentationFile); } } finally { File.Delete(documentationFile); } // Do the diff if (codeGenOptions.FailOnDiff) { TestHelper.ValidateFilesEqual(codeGenOptions.RelativeTestDir, codeGenOptions.RelativeDeployDir, generatedFileName, referenceFileName, codeGenOptions.Language); } else { TestHelper.FilesMatch(codeGenOptions.RelativeTestDir, codeGenOptions.RelativeDeployDir, generatedFileName, referenceFileName, codeGenOptions.Language, out diffMessage); } return diffMessage; }
// Invokes the code generator discovered via the host and options internal static string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable<Type> domainServiceTypes) { IDomainServiceClientCodeGenerator generator = CreateCodeGenerator(host, options); DomainServiceCatalog catalog = new DomainServiceCatalog(domainServiceTypes, host as ILogger); return generator.GenerateCode(host, catalog.DomainServiceDescriptions, options); }
/// <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="OpenRiaServices.DomainServices.Server.DomainService"/> 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> private string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, DomainServiceCatalog 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<DomainServiceDescription> domainServiceDescriptions = catalog.DomainServiceDescriptions; IDomainServiceClientCodeGenerator proxyGenerator = this.FindCodeGenerator(host, options, compositionAssemblies, codeGeneratorName); string generatedCode = null; if (proxyGenerator != null) { try { generatedCode = proxyGenerator.GenerateCode(host, domainServiceDescriptions, 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; }
/// <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="domainServiceTypes">The set of <see cref="OpenRiaServices.DomainServices.Server.DomainService"/> 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> internal string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable<Type> domainServiceTypes, IEnumerable<string> compositionAssemblies, string codeGeneratorName) { Debug.Assert(host != null, "host cannot be null"); Debug.Assert(options != null, "options cannot be null"); Debug.Assert(domainServiceTypes != null, "domainServiceTypes cannot be null"); ILogger logger = host as ILogger; DomainServiceCatalog catalog = new DomainServiceCatalog(domainServiceTypes, 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="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> internal 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"); ILogger logger = host as ILogger; DomainServiceCatalog catalog = new DomainServiceCatalog(assembliesToLoad, logger); return this.GenerateCode(host, options, catalog, assembliesToLoad, codeGeneratorName); }