/// <summary> /// Creates the MEF composition container to use for code generation. /// </summary> /// <remarks> /// This container is constructed from the specified set of <paramref name="compositionAssemblyPaths"/> /// and serves as the context in which to find code generators. /// </remarks> /// <param name="compositionAssemblyPaths">Optional set of assembly locations to add to container.</param> /// <param name="logger"><see cref="ILogger"/> instance to report issues.</param> private void CreateCompositionContainer(IEnumerable <string> compositionAssemblyPaths, ILogger logger) { Debug.Assert(this._compositionContainer == null, "The composition container cannot be created twice"); Debug.Assert(logger != null, "logger cannot be null"); try { // This code creates a MEF composition container from all the assemblies of this solution IEnumerable <AssemblyCatalog> catalogs = ClientCodeGenerationDispatcher.GetCompositionAssemblies(compositionAssemblyPaths, logger).Select <Assembly, AssemblyCatalog>(a => new AssemblyCatalog(a)); this._partCatalog = new AggregateCatalog(catalogs); this._compositionContainer = new CompositionContainer(this._partCatalog); // Add this instance to the container to satisfy the [ImportMany] this._compositionContainer.ComposeParts(this); } catch (Exception ex) { // An exception is possible in situations where the user has included // reference assemblies that cause TypeLoadFailures. If we encounter // this situation, fallback to using only our current assembly as the // catalog. This allows MEF to still work for types in this assembly. logger.LogWarning(string.Format(CultureInfo.CurrentCulture, Resource.Failed_To_Create_Composition_Container, ex.Message)); this._partCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); this._compositionContainer = new CompositionContainer(this._partCatalog); this._compositionContainer.ComposeParts(this); } }
/// <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; }
// Locates the code generator registered to work with the language for the given options internal static IDomainServiceClientCodeGenerator CreateCodeGenerator(ICodeGenerationHost host, ClientCodeGenerationOptions options) { using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { IDomainServiceClientCodeGenerator generator = dispatcher.FindCodeGenerator(host, options, /*compositionAssemblies*/ null, /*codeGeneratorName*/ null); return generator; } }