public async Task Combined_IncrementalProgressUpdates() { var discovery = PartDiscovery.Combine(TestUtilities.V2Discovery, TestUtilities.V1Discovery); var assemblies = new[] { typeof(AssemblyDiscoveryTests.DiscoverablePart1).GetTypeInfo().Assembly, this.GetType().GetTypeInfo().Assembly, }; DiscoveryProgress lastReceivedUpdate = default(DiscoveryProgress); int progressUpdateCount = 0; var progress = new SynchronousProgress <DiscoveryProgress>(update => { progressUpdateCount++; Assert.NotNull(update.Status); ////Assert.True(update.Completion >= lastReceivedUpdate.Completion); // work can be discovered that regresses this legitimately Assert.True(update.Completion <= 1); Assert.True(update.Status != lastReceivedUpdate.Status || update.Completion != lastReceivedUpdate.Completion); this.output.WriteLine( "Completion reported: {0} ({1}/{2}): {3}", update.Completion, update.CompletedSteps, update.TotalSteps, update.Status); lastReceivedUpdate = update; }); await discovery.CreatePartsAsync(assemblies, progress); progress.RethrowAnyExceptions(); Assert.True(lastReceivedUpdate.Completion > 0); Assert.True(progressUpdateCount > 2); }
private IReadOnlyList <PartDiscovery> GetV3DiscoveryModules() { var titleAppends = new List <string>(); var discovery = new List <PartDiscovery>(); if (this.compositionVersions.HasFlag(CompositionEngines.V3EmulatingV1)) { #if DESKTOP discovery.Add(TestUtilities.V1Discovery); titleAppends.Add("V1"); #endif } var v2Discovery = this.compositionVersions.HasFlag(CompositionEngines.V3EmulatingV2WithNonPublic) ? TestUtilities.V2DiscoveryWithNonPublics : TestUtilities.V2Discovery; if (this.compositionVersions.HasFlag(CompositionEngines.V3EmulatingV2)) { discovery.Add(v2Discovery); titleAppends.Add("V2"); } if (this.compositionVersions.HasFlag(CompositionEngines.V3EmulatingV1AndV2AtOnce)) { #if DESKTOP discovery.Add(PartDiscovery.Combine(TestUtilities.V1Discovery, v2Discovery)); titleAppends.Add("V1+V2"); #endif } this.DisplayName += " (" + string.Join(", ", titleAppends) + ")"; return(discovery); }
public async Task Initialize() { if (_initialized) { return; } var discovery = PartDiscovery.Combine(new AttributedPartDiscoveryV1(Resolver.DefaultInstance)); var catalog = ComposableCatalog.Create(Resolver.DefaultInstance) .AddParts(await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly())) .AddParts(await discovery.CreatePartsAsync(Assembly.GetCallingAssembly())) .AddParts(await discovery.CreatePartsAsync(Assembly.GetEntryAssembly())) .AddParts(await discovery.CreatePartsAsync(_directoryCatalog.Assemblies)) .WithCompositionService(); // Makes an ICompositionService export available to MEF parts to import // Assemble the parts into a valid graph. var config = CompositionConfiguration.Create(catalog); // Prepare an ExportProvider factory based on this graph. Factory = config.CreateExportProviderFactory(); // Create an export provider, which represents a unique container of values. ExportProvider = Factory.CreateExportProvider(); CompositionService = ExportProvider.GetExportedValue <ICompositionService>(); _initialized = true; }
public async Task Combined_CreatePartsAsync_TypeArray_ResilientAgainstReflectionErrors() { var discovery = PartDiscovery.Combine(new SketchyPartDiscovery(), new NoOpDiscovery()); var parts = await discovery.CreatePartsAsync(typeof(string), typeof(int)); Assert.Equal(1, parts.DiscoveryErrors.Count); Assert.Equal(1, parts.Parts.Count); }
public void Combine_JustOneButWithDifferentResolver() { LoggingAssemblyLoader assemblyLoader = new(); Resolver assemblyResolver = new(assemblyLoader); PartDiscovery combined = PartDiscovery.Combine(assemblyResolver, TestUtilities.V1Discovery); Assert.NotSame(TestUtilities.V1Discovery, combined); Assert.Same(assemblyResolver, combined.Resolver); }
public override bool Execute() { var resolver = Resolver.DefaultInstance; var discovery = PartDiscovery.Combine(new AttributedPartDiscoveryV1(resolver), new AttributedPartDiscovery(resolver, isNonPublicSupported: true)); this.CancellationToken.ThrowIfCancellationRequested(); var parts = discovery.CreatePartsAsync(this.CatalogAssemblies.Select(item => item.ItemSpec)).GetAwaiter().GetResult(); foreach (var error in parts.DiscoveryErrors) { this.Log.LogWarningFromException(error); } this.CancellationToken.ThrowIfCancellationRequested(); var catalog = ComposableCatalog.Create(resolver) .AddParts(parts.Parts); this.CancellationToken.ThrowIfCancellationRequested(); var configuration = CompositionConfiguration.Create(catalog); if (!string.IsNullOrEmpty(this.DgmlOutputPath)) { configuration.CreateDgml().Save(this.DgmlOutputPath); } this.CancellationToken.ThrowIfCancellationRequested(); if (!configuration.CompositionErrors.IsEmpty) { foreach (var error in configuration.CompositionErrors.Peek()) { this.Log.LogError(error.Message); } 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(); } return(!this.Log.HasLoggedErrors); }
public async Task Combined_CreatePartsAsync_AssemblyPathEnumerable() { var discovery = PartDiscovery.Combine(TestUtilities.V2Discovery, TestUtilities.V1Discovery); var assemblies = new[] { typeof(AssemblyDiscoveryTests.DiscoverablePart1).GetTypeInfo().Assembly, this.GetType().GetTypeInfo().Assembly, }; var parts = await discovery.CreatePartsAsync(assemblies.Select(a => a.Location)); Assert.NotEqual(0, parts.Parts.Count); }
public async Task DiscoveriesCombinedWithResolver() { LoggingAssemblyLoader assemblyLoader = new(); Resolver assemblyResolver = new(assemblyLoader); PartDiscovery combined = PartDiscovery.Combine(assemblyResolver, TestUtilities.V2Discovery, TestUtilities.V1Discovery); Assert.Same(assemblyResolver, combined.Resolver); string testAssemblyPath = typeof(PartDiscoveryTests).Assembly.Location; await combined.CreatePartsAsync(new string[] { testAssemblyPath }); Assert.Equal(new[] { testAssemblyPath }, assemblyLoader.AttemptedAssemblyPaths); }
public async Task AssemblyDiscoveryOmitsNonDiscoverableParts_Combined() { var combined = PartDiscovery.Combine(this.DiscoveryService, new PartDiscoveryAllTypesMock()); var result = await combined.CreatePartsAsync(typeof(NonDiscoverablePart).GetTypeInfo().Assembly); Assert.False(result.Parts.Any(p => p.Type.GetTypeInfo().IsEquivalentTo(typeof(NonPart)))); Assert.False(result.Parts.Any(p => p.Type.GetTypeInfo().IsEquivalentTo(typeof(NonDiscoverablePart)))); Assert.False(result.Parts.Any(p => p.Type.GetTypeInfo().IsEquivalentTo(typeof(NonDiscoverablePartV1)))); Assert.False(result.Parts.Any(p => p.Type.GetTypeInfo().IsEquivalentTo(typeof(NonDiscoverablePartV2)))); Assert.True(result.Parts.Any(p => p.Type.GetTypeInfo().IsEquivalentTo(typeof(DiscoverablePart1)))); Assert.True(result.Parts.Any(p => p.Type.GetTypeInfo().IsEquivalentTo(typeof(DiscoverablePart2)))); }
private static ExportProvider CreateExportProvider(string applicationDataFolder) { var stopwatch = Stopwatch.StartNew(); var file = new FileInfo(Application.ExecutablePath); FileInfo[] plugins = Directory.Exists(Path.Combine(file.Directory.FullName, "Plugins")) ? new DirectoryInfo(Path.Combine(file.Directory.FullName, "Plugins")).GetFiles("*.dll") : new FileInfo[] { }; var pluginFiles = plugins; var cacheFile = Path.Combine(applicationDataFolder ?? "ignored", "Plugins", "composition.cache"); IExportProviderFactory exportProviderFactory; if (applicationDataFolder != null && File.Exists(cacheFile)) { using (var cacheStream = File.OpenRead(cacheFile)) { exportProviderFactory = ThreadHelper.JoinableTaskFactory.Run(() => new CachedComposition().LoadExportProviderFactoryAsync(cacheStream, Resolver.DefaultInstance)); } } else { var assemblies = pluginFiles.Select(assemblyFile => TryLoadAssembly(assemblyFile)).Where(assembly => assembly != null).ToArray(); var discovery = PartDiscovery.Combine( new AttributedPartDiscoveryV1(Resolver.DefaultInstance), new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true)); var parts = ThreadHelper.JoinableTaskFactory.Run(() => discovery.CreatePartsAsync(assemblies)); var catalog = ComposableCatalog.Create(Resolver.DefaultInstance).AddParts(parts); var configuration = CompositionConfiguration.Create(catalog.WithCompositionService()); var runtimeComposition = RuntimeComposition.CreateRuntimeComposition(configuration); if (applicationDataFolder != null) { #if false // Composition caching currently disabled Directory.CreateDirectory(Path.Combine(applicationDataFolder, "Plugins")); using (var cacheStream = File.OpenWrite(cacheFile)) { ThreadHelper.JoinableTaskFactory.Run(() => new CachedComposition().SaveAsync(runtimeComposition, cacheStream)); } #endif } exportProviderFactory = runtimeComposition.CreateExportProviderFactory(); } return(exportProviderFactory.CreateExportProvider()); }
internal void CreateCache(string assemblyPath, Stream cacheStream, out int metadataToken) { Requires.NotNullOrEmpty(assemblyPath, nameof(assemblyPath)); var resolver = new Resolver(new CustomAssemblyLoader(assemblyPath)); var discovery = PartDiscovery.Combine( new AttributedPartDiscovery(resolver, isNonPublicSupported: true), new AttributedPartDiscoveryV1(resolver)); var discoveredParts = discovery.CreatePartsAsync(new[] { assemblyPath }).GetAwaiter().GetResult(); var catalog = ComposableCatalog.Create(resolver) .AddParts(discoveredParts); var configuration = CompositionConfiguration.Create(catalog); this.cacheManager.SaveAsync(configuration, cacheStream).GetAwaiter().GetResult(); metadataToken = GetMetadataTokenForDefaultCtor(catalog.Parts.Single(p => p.TypeRef.FullName == typeof(DiscoverablePart1).FullName).Type); }
public static async Task <ComposableCatalog> CreateCatalog(HashSet <Assembly> assemblies = null) { Resolver StandardResolver = Resolver.DefaultInstance; PartDiscovery Discovery = PartDiscovery.Combine( new AttributedPartDiscoveryV1(StandardResolver), new AttributedPartDiscovery(StandardResolver, true)); var parts = await Discovery.CreatePartsAsync(assemblies ?? ReadAssembliesFromAddins()); ComposableCatalog catalog = ComposableCatalog.Create(StandardResolver) .WithCompositionService() .WithDesktopSupport() .AddParts(parts); return(catalog); }
private static PartDiscovery GetDiscoveryService(CompositionEngines attributesDiscovery) { var discovery = new List <PartDiscovery>(2); if (attributesDiscovery.HasFlag(CompositionEngines.V1)) { discovery.Add(V1Discovery); } if (attributesDiscovery.HasFlag(CompositionEngines.V2)) { var v2Discovery = attributesDiscovery.HasFlag(CompositionEngines.V3NonPublicSupport) ? V2DiscoveryWithNonPublics : V2Discovery; discovery.Add(v2Discovery); } return(PartDiscovery.Combine(discovery.ToArray())); }
private async Task <ExportProvider> Compose(object parentInstance) { ExportProvider exportProvider = null; PartDiscovery discovery = PartDiscovery.Combine( new AttributedPartDiscovery(Resolver.DefaultInstance), new AttributedPartDiscoveryV1(Resolver.DefaultInstance)); // ".NET MEF" attributes (System.ComponentModel.Composition) Assembly parentAssembly = parentInstance.GetType().Assembly; string parentLocation = parentAssembly.Location; string assemblyPath = parentLocation; assemblyPath = assemblyPath.Substring(0, assemblyPath.LastIndexOf('\\')); Helpers desktopBridgeHelper = new Helpers(); List <string> assemblies = new[] { parentLocation } .Concat( Directory.EnumerateFiles(assemblyPath, "*.dll", SearchOption.TopDirectoryOnly) .Where(_ => _.Contains("NUnit3GUI"))) .ToList(); DiscoveredParts discoveredParts = await discovery.CreatePartsAsync(assemblies); discoveredParts.ThrowOnErrors(); ComposableCatalog catalog = ComposableCatalog.Create(Resolver.DefaultInstance) .AddParts(discoveredParts) .WithCompositionService(); CompositionConfiguration config = CompositionConfiguration.Create(catalog); config.ThrowOnErrors(); IExportProviderFactory epf = config.CreateExportProviderFactory(); exportProvider = epf.CreateExportProvider(); ICompositionService service = exportProvider.GetExportedValue <ICompositionService>(); service.SatisfyImportsOnce(parentInstance); return(exportProvider); }
public ComponentComposition() { var discovery = PartDiscovery.Combine(new AttributedPartDiscoveryV1(Resolver.DefaultInstance), new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true)); var parts = discovery.CreatePartsAsync(BuildInAssemblies).GetAwaiter().GetResult(); var scopeParts = discovery.CreatePartsAsync(typeof(UnconfiguredProjectScope), typeof(ConfiguredProjectScope), typeof(ProjectServiceScope), typeof(GlobalScope)).GetAwaiter().GetResult(); ComposableCatalog catalog = ComposableCatalog.Create(Resolver.DefaultInstance) .AddParts(parts) .AddParts(scopeParts) .WithCompositionService(); // Prepare the self-host service and composition Catalog = catalog; Configuration = CompositionConfiguration.Create(catalog); Contracts = CollectContractMetadata(ContractAssemblies.Union(BuildInAssemblies)); ContractsRequiringAppliesTo = CollectContractsRequiringAppliesTo(catalog); InterfaceNames = CollectInterfaceNames(ContractAssemblies); }
public static PartDiscovery CreatePartDiscovery(Resolver resolver) { return(PartDiscovery.Combine(new AttributedPartDiscoveryV1(resolver), new AttributedPartDiscovery(resolver, isNonPublicSupported: true))); }
public void Combine_JustOneButWithSameResolver() { PartDiscovery combined = PartDiscovery.Combine(TestUtilities.V1Discovery.Resolver, TestUtilities.V1Discovery); Assert.Same(TestUtilities.V1Discovery, combined); }
/// <summary> /// Creates a reusable environment that consists of /// 1) default parts and parts needed to bootstrap the editor, except for parts whose metadata matches these from <paramref name="typesThatOverride"></paramref> /// 2) parts found in the provided assemblies /// 3) parts found in the provided types. /// </summary> /// <param name="assembliesToLoad">Filenames of assemblies that will be searched for MEF parts.</param> /// <param name="typesToLoad">Types to include in the MEF catalog.</param> /// <param name="typesThatOverride">Types whose export signatures will be used to filter out the default catalog.</param> /// <returns>Composed environment that can be reused across tests</returns> public static async Task <EditorEnvironment> InitializeAsync(IEnumerable <string> assembliesToLoad, IEnumerable <Type> typesToLoad, IEnumerable <Type> typesThatOverride) { // Prepare part discovery to support both flavors of MEF attributes. var discovery = PartDiscovery.Combine( new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true), // "NuGet MEF" attributes (Microsoft.Composition) new AttributedPartDiscoveryV1(Resolver.DefaultInstance)); // ".NET MEF" attributes (System.ComponentModel.Composition) var assemblyCatalog = ComposableCatalog.Create(Resolver.DefaultInstance); // Create a list of parts that should override the defaults. Used for mocking when Import expects only one part. IEnumerable <ComposablePartDefinition> partsThatOverride = null; if (typesThatOverride != null) { partsThatOverride = (await discovery.CreatePartsAsync(typesThatOverride)).Parts; } // Load default parts foreach (var assemblyName in DefaultAssemblies) { try { var parts = (await discovery.CreatePartsAsync(Assembly.LoadFrom(assemblyName))).Parts; if (partsThatOverride != null) { // Exclude parts whose contract matches the contract of any of the overriding parts var overriddenParts = parts.Where(defaultPart => defaultPart.ExportedTypes.Any(defaultType => partsThatOverride.Any(overridingPart => overridingPart.ExportedTypes.Any(overridingType => overridingType.ContractName == defaultType.ContractName)))); parts = parts.Except(overriddenParts); } assemblyCatalog = assemblyCatalog.AddParts(parts); } catch (System.IO.FileNotFoundException) { // Note, if we provide inner exception, the MSTest runner will display it instead of informativeException. For this reason, we don't provide inner exception. var informativeException = new InvalidOperationException($"Required assembly `{assemblyName}` not found. Please place it in this process' working directory. You can do it by adding reference to the NuGet package that contains this assembly."); informativeException.Data["Missing file"] = assemblyName; throw informativeException; } } // Load parts from all types in the specified assemblies if (assembliesToLoad != null) { foreach (string assembly in assembliesToLoad) { var parts = await discovery.CreatePartsAsync(Assembly.LoadFrom(assembly)); assemblyCatalog = assemblyCatalog.AddParts(parts); } } // Load parts from the specified types if (typesToLoad != null) { var parts = await discovery.CreatePartsAsync(typesToLoad); assemblyCatalog = assemblyCatalog.AddParts(parts); } // TODO: see if this will be useful assemblyCatalog = assemblyCatalog.WithCompositionService(); // Makes an ICompositionService export available to MEF parts to import. // Assemble the parts into a valid graph. var compositionConfiguration = CompositionConfiguration.Create(assemblyCatalog); ImmutableArray <string> compositionErrors = ImmutableArray <string> .Empty; if (compositionConfiguration.CompositionErrors.Any()) { compositionErrors = compositionConfiguration.CompositionErrors.SelectMany(collection => collection.Select(diagnostic => diagnostic.Message)).ToImmutableArray(); // Uncomment to investigate errors and continue execution // Debugger.Break(); // Uncomment to fail immediately: // var exception = new InvalidOperationException("There were composition errors"); // exception.Data["Errors"] = errors; // throw exception; } // Prepare an ExportProvider factory based on this graph. // This factory can be now re-used across tests return(new EditorEnvironment(compositionConfiguration.CreateExportProviderFactory(), compositionErrors)); }
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(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(); } }