public CompositionConfiguration GetCompositionConfiguration() => CompositionConfiguration.Create(GetCatalog());
protected override async Task <RunSummary> RunTestAsync() { var output = new TestOutputHelper(); output.Initialize(this.MessageBus, new XunitTest(this.TestCase, this.DisplayName)); await this.Aggregator.RunAsync(() => this.Timer.AggregateAsync( async delegate { var v3DiscoveryModules = this.GetV3DiscoveryModules(); var resultingCatalogs = new List <ComposableCatalog>(v3DiscoveryModules.Count); var assemblies = this.assemblyNames.Select(an => Assembly.Load(new AssemblyName(an))).ToList(); foreach (var discoveryModule in v3DiscoveryModules) { var partsFromTypes = await discoveryModule.CreatePartsAsync(this.parts); var partsFromAssemblies = await discoveryModule.CreatePartsAsync(assemblies); var catalog = TestUtilities.EmptyCatalog .AddParts(partsFromTypes) .AddParts(partsFromAssemblies); resultingCatalogs.Add(catalog); } string[] catalogStringRepresentations = resultingCatalogs.Select(catalog => { var writer = new StringWriter(); catalog.ToString(writer); return(writer.ToString()); }).ToArray(); bool anyStringRepresentationDifferences = false; for (int i = 1; i < resultingCatalogs.Count; i++) { anyStringRepresentationDifferences = PrintDiff( v3DiscoveryModules[0].GetType().Name, v3DiscoveryModules[i].GetType().Name, catalogStringRepresentations[0], catalogStringRepresentations[i], output); } // Verify that the catalogs are identical. // The string compare above should have taken care of this (in a more descriptive way), // but we do this to double-check. var uniqueCatalogs = resultingCatalogs.Distinct().ToArray(); // Fail the test if ComposableCatalog.Equals returns a different result from string comparison. Assert.Equal(anyStringRepresentationDifferences, uniqueCatalogs.Length > 1); if (uniqueCatalogs.Length == 1) { ////output.WriteLine(catalogStringRepresentations[0]); } // For each distinct catalog, create one configuration and verify it meets expectations. var configurations = new List <CompositionConfiguration>(uniqueCatalogs.Length); foreach (var uniqueCatalog in uniqueCatalogs) { var catalogWithSupport = uniqueCatalog #if DESKTOP .WithCompositionService() #endif ; // Round-trip the catalog through serialization to verify that as well. await RoundtripCatalogSerializationAsync(catalogWithSupport, output); var configuration = CompositionConfiguration.Create(catalogWithSupport); if (!this.compositionVersions.HasFlag(CompositionEngines.V3AllowConfigurationWithErrors)) { Assert.Equal(this.expectInvalidConfiguration, !configuration.CompositionErrors.IsEmpty || !catalogWithSupport.DiscoveredParts.DiscoveryErrors.IsEmpty); } // Save the configuration in a property so that the engine test that follows can reuse the work we've done. configurations.Add(configuration); } this.ResultingConfigurations = configurations; })); var test = new XunitTest(this.TestCase, this.DisplayName); var runSummary = new RunSummary { Total = 1, Time = this.Timer.Total }; IMessageSinkMessage testResultMessage; if (this.Aggregator.HasExceptions) { testResultMessage = new TestFailed(test, this.Timer.Total, output.Output, this.Aggregator.ToException()); runSummary.Failed++; } else { testResultMessage = new TestPassed(test, this.Timer.Total, output.Output); this.Passed = true; } if (!this.MessageBus.QueueMessage(testResultMessage)) { this.CancellationTokenSource.Cancel(); } this.Aggregator.Clear(); return(runSummary); }
public Mef3TestCaseRunner(IXunitTestCase testCase, string displayName, string skipReason, object[] constructorArguments, IMessageBus messageBus, ExceptionAggregator aggregator, CancellationTokenSource cancellationTokenSource, CompositionConfiguration configuration, CompositionEngines compositionVersions) : base(testCase, displayName, skipReason, constructorArguments, null, messageBus, aggregator, cancellationTokenSource) { Requires.NotNull(configuration, nameof(configuration)); this.configuration = configuration; this.compositionVersions = compositionVersions; }
public SingleExportProviderFactory(Scope scope, ComposableCatalog catalog, CompositionConfiguration configuration, IExportProviderFactory exportProviderFactory) { _scope = scope; _catalog = catalog; _configuration = configuration; _exportProviderFactory = exportProviderFactory; }
private static async Task InitializeMef() { // Cannot show MessageBox here, because WPF would crash with a XamlParseException // Remember and show exceptions in text output, once MainWindow is properly initialized try { // Set up VS MEF. For now, only do MEF1 part discovery, since that was in use before. // To support both MEF1 and MEF2 parts, just change this to: // var discovery = PartDiscovery.Combine(new AttributedPartDiscoveryV1(Resolver.DefaultInstance), // new AttributedPartDiscovery(Resolver.DefaultInstance)); var discovery = new AttributedPartDiscoveryV1(Resolver.DefaultInstance); var catalog = ComposableCatalog.Create(Resolver.DefaultInstance); var pluginDir = Path.GetDirectoryName(typeof(App).Module.FullyQualifiedName); #if NET472 if (pluginDir != null) { foreach (var plugin in Directory.GetFiles(pluginDir, "*.Plugin.dll")) { var name = Path.GetFileNameWithoutExtension(plugin); try { var asm = Assembly.Load(name); var parts = await discovery.CreatePartsAsync(asm); catalog = catalog.AddParts(parts); } catch (Exception ex) { StartupExceptions.Add(new ExceptionData { Exception = ex, PluginName = name }); } } } #endif // Add the built-in parts var createdParts = await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly()); catalog = catalog.AddParts(createdParts); // If/When the project switches to .NET Standard/Core, this will be needed to allow metadata interfaces (as opposed // to metadata classes). When running on .NET Framework, it's automatic. // catalog.WithDesktopSupport(); // If/When any part needs to import ICompositionService, this will be needed: // catalog.WithCompositionService(); var config = CompositionConfiguration.Create(catalog); ExportProviderFactory = config.CreateExportProviderFactory(); ExportProvider = ExportProviderFactory.CreateExportProvider(); // This throws exceptions for composition failures. Alternatively, the configuration's CompositionErrors property // could be used to log the errors directly. Used at the end so that it does not prevent the export provider setup. config.ThrowOnErrors(); } catch (CompositionFailedException ex) when(ex.InnerException is AggregateException agex) { foreach (var inner in agex.InnerExceptions) { StartupExceptions.Add(new ExceptionData { Exception = inner }); } } catch (Exception ex) { StartupExceptions.Add(new ExceptionData { Exception = ex }); } }
public override bool Execute() { if (Environment.GetEnvironmentVariable("CreateCompositionTaskDebug") == "1") { Debugger.Launch(); } this.catalogAssemblyPaths.AddRange(this.CatalogAssemblies.Select(this.GetMEFAssemblyFullPath)); AppDomain.CurrentDomain.AssemblyResolve += this.CurrentDomain_AssemblyResolve; try { var loadableAssemblies = this.catalogAssemblyPaths .Concat(this.ReferenceAssemblies.Select(i => i.GetMetadata("FullPath")) ?? Enumerable.Empty <string>()); var resolver = new Resolver(new AssemblyLoader(this, loadableAssemblies)); var discovery = PartDiscovery.Combine( new AttributedPartDiscoveryV1(resolver), new AttributedPartDiscovery(resolver, isNonPublicSupported: true)); this.CancellationToken.ThrowIfCancellationRequested(); var parts = discovery.CreatePartsAsync(this.catalogAssemblyPaths).GetAwaiter().GetResult(); var catalog = ComposableCatalog.Create(resolver) .AddParts(parts); this.LogLines(this.GetLogFilePath("CatalogAssemblies"), this.GetCatalogAssembliesLines(catalog), this.CancellationToken); string catalogErrorFilePath = this.GetLogFilePath("CatalogErrors"); if (catalog.DiscoveredParts.DiscoveryErrors.IsEmpty) { File.Delete(catalogErrorFilePath); } else { this.LogLines(catalogErrorFilePath, GetCatalogErrorLines(catalog), this.CancellationToken); foreach (var error in catalog.DiscoveredParts.DiscoveryErrors) { string message = error.GetUserMessage(); if (this.ContinueOnDiscoveryErrors) { this.LogWarning(DiscoveryErrorCode, message); } else { this.Log.LogError(null, DiscoveryErrorCode, null, null, 0, 0, 0, 0, message); } } if (!this.ContinueOnDiscoveryErrors) { return(false); } } this.CancellationToken.ThrowIfCancellationRequested(); var configuration = CompositionConfiguration.Create(catalog); if (!string.IsNullOrEmpty(this.DgmlOutputPath)) { configuration.CreateDgml().Save(this.DgmlOutputPath); this.writtenFiles.Add(this.DgmlOutputPath !); } this.CancellationToken.ThrowIfCancellationRequested(); string compositionLogPath = this.GetLogFilePath("CompositionErrors"); if (configuration.CompositionErrors.IsEmpty) { File.Delete(compositionLogPath); } else { this.LogLines(compositionLogPath, GetCompositionErrorLines(configuration), this.CancellationToken); foreach (var error in configuration.CompositionErrors.Peek()) { if (this.ContinueOnCompositionErrors) { this.LogWarning(CompositionErrorCode, error.Message); } else { this.Log.LogError(null, CompositionErrorCode, null, null, 0, 0, 0, 0, error.Message); } } if (!this.ContinueOnCompositionErrors) { return(false); } } this.CancellationToken.ThrowIfCancellationRequested(); string cachePath = Path.GetFullPath(this.CompositionCacheFile); this.Log.LogMessage("Producing IoC container \"{0}\"", cachePath); using (var cacheStream = File.Open(cachePath, FileMode.Create)) { this.CancellationToken.ThrowIfCancellationRequested(); var runtime = RuntimeComposition.CreateRuntimeComposition(configuration); this.CancellationToken.ThrowIfCancellationRequested(); var runtimeCache = new CachedComposition(); runtimeCache.SaveAsync(runtime, cacheStream, this.CancellationToken).GetAwaiter().GetResult(); } this.writtenFiles.Add(cachePath); return(!this.Log.HasLoggedErrors); } finally { AppDomain.CurrentDomain.AssemblyResolve -= this.CurrentDomain_AssemblyResolve; this.FileWrites = this.writtenFiles.Select(f => new TaskItem(f)).ToArray(); } }
/// <summary> /// Method to initialize the part nodes and thier "pointers" based on the error /// stack from the config. /// </summary> private void GenerateNodeGraph() { // Get the error stack from the composition configuration var expectedRejectionsChecker = new ExpectedRejections(this.Options); CompositionConfiguration config = this.Creator.Config !; var errors = config.CompositionErrors; int levelNumber = 1; while (errors.Count() > 0) { // Process all the parts present in the current level of the stack var currentLevel = errors.Peek(); foreach (var element in currentLevel) { var part = element.Parts.First(); // Create a PartNode object from the definition of the current Part ComposablePartDefinition definition = part.Definition; string currentName = definition.Type.FullName !; if (currentName == null) { continue; } if (this.RejectionGraph.ContainsKey(currentName)) { this.RejectionGraph[currentName].AddErrorMessage(element.Message); continue; } PartNode currentNode = new PartNode(definition, element.Message, levelNumber); currentNode.IsRejectionExpected = expectedRejectionsChecker.IsRejectionExpected(currentName); this.RejectionGraph.Add(currentName, currentNode); } // Get the next level of the stack errors = errors.Pop(); levelNumber += 1; } this.MaxLevels = levelNumber - 1; foreach (var nodePair in this.RejectionGraph) { var node = nodePair.Value; var currentNodeName = node.Name; var nodeDefinition = node.Part; // Get the imports for the current part to update the pointers associated with the current node foreach (var import in nodeDefinition.Imports) { string importName = import.ImportingSiteType.FullName !; if (importName == null || !this.RejectionGraph.ContainsKey(importName)) { continue; } string importLabel = importName; if (import.ImportingMember != null) { importLabel = import.ImportingMember.Name; } PartNode childNode = this.RejectionGraph[importName]; childNode.AddParent(node, importLabel); node.AddChild(childNode, importLabel); } } }
public App() { var cmdArgs = Environment.GetCommandLineArgs().Skip(1); App.CommandLineArguments = new CommandLineArguments(cmdArgs); if ((App.CommandLineArguments.SingleInstance ?? true) && !MiscSettingsPanel.CurrentMiscSettings.AllowMultipleInstances) { cmdArgs = cmdArgs.Select(FullyQualifyPath); string message = string.Join(Environment.NewLine, cmdArgs); if (SendToPreviousInstance("ILSpy:\r\n" + message, !App.CommandLineArguments.NoActivate)) { Environment.Exit(0); } } InitializeComponent(); // Cannot show MessageBox here, because WPF would crash with a XamlParseException // Remember and show exceptions in text output, once MainWindow is properly initialized try { // Set up VS MEF. For now, only do MEF1 part discovery, since that was in use before. // To support both MEF1 and MEF2 parts, just change this to: // var discovery = PartDiscovery.Combine(new AttributedPartDiscoveryV1(Resolver.DefaultInstance), // new AttributedPartDiscovery(Resolver.DefaultInstance)); var discovery = new AttributedPartDiscoveryV1(Resolver.DefaultInstance); var catalog = ComposableCatalog.Create(Resolver.DefaultInstance); var pluginDir = Path.GetDirectoryName(typeof(App).Module.FullyQualifiedName); if (pluginDir != null) { foreach (var plugin in Directory.GetFiles(pluginDir, "*.Plugin.dll")) { var name = Path.GetFileNameWithoutExtension(plugin); try { var asm = Assembly.Load(name); var parts = discovery.CreatePartsAsync(asm).Result; catalog = catalog.AddParts(parts); } catch (Exception ex) { StartupExceptions.Add(new ExceptionData { Exception = ex, PluginName = name }); } } } // Add the built-in parts catalog = catalog.AddParts(discovery.CreatePartsAsync(Assembly.GetExecutingAssembly()).Result); // If/When the project switches to .NET Standard/Core, this will be needed to allow metadata interfaces (as opposed // to metadata classes). When running on .NET Framework, it's automatic. // catalog.WithDesktopSupport(); // If/When any part needs to import ICompositionService, this will be needed: // catalog.WithCompositionService(); var config = CompositionConfiguration.Create(catalog); exportProviderFactory = config.CreateExportProviderFactory(); exportProvider = exportProviderFactory.CreateExportProvider(); // This throws exceptions for composition failures. Alternatively, the configuration's CompositionErrors property // could be used to log the errors directly. Used at the end so that it does not prevent the export provider setup. config.ThrowOnErrors(); } catch (Exception ex) { StartupExceptions.Add(new ExceptionData { Exception = ex }); } if (!System.Diagnostics.Debugger.IsAttached) { AppDomain.CurrentDomain.UnhandledException += ShowErrorBox; Dispatcher.CurrentDispatcher.UnhandledException += Dispatcher_UnhandledException; } TaskScheduler.UnobservedTaskException += DotNet40_UnobservedTaskException; Languages.Initialize(exportProvider); EventManager.RegisterClassHandler(typeof(Window), Hyperlink.RequestNavigateEvent, new RequestNavigateEventHandler(Window_RequestNavigate)); ILSpyTraceListener.Install(); }