/// <summary>
        /// Initializes a new instance of the <see cref="NetCoreAssemblyDependencyResolver"/> class.
        /// </summary>
        /// <param name="assemblyFilePath">The path to the assembly</param>
        /// <param name="internalDiagnosticsMessageSink">An optional message sink for use with internal diagnostics messages;
        /// may pass <c>null</c> for no internal diagnostics messages</param>
        public NetCoreAssemblyDependencyResolver(string assemblyFilePath, IMessageSink internalDiagnosticsMessageSink)
        {
            this.internalDiagnosticsMessageSink = internalDiagnosticsMessageSink;

            var assembly = LoadFromAssemblyPath(assemblyFilePath);

            assemblyFolder    = Path.GetDirectoryName(assemblyFilePath);
            assemblyResolver  = new XunitPackageCompilationAssemblyResolver();
            dependencyContext = DependencyContext.Load(assembly);

            var compatibleRuntimes = default(HashSet <string>);
            var currentRuntime     = RuntimeEnvironment.GetRuntimeIdentifier();
            var fallbacks          = dependencyContext.RuntimeGraph.FirstOrDefault(x => string.Equals(x.Runtime, currentRuntime, StringComparison.OrdinalIgnoreCase));

            if (fallbacks != null)
            {
                compatibleRuntimes = new HashSet <string>(fallbacks.Fallbacks, StringComparer.OrdinalIgnoreCase);
            }
            else
            {
                compatibleRuntimes = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            }

            compatibleRuntimes.Add(currentRuntime);
            compatibleRuntimes.Add(string.Empty);

            managedAssemblyCache = new Dictionary <string, Assembly>(StringComparer.OrdinalIgnoreCase);
            managedAssemblyMap   =
                dependencyContext.RuntimeLibraries
                .Where(lib => lib.RuntimeAssemblyGroups?.Count > 0)
                .Select(lib => Tuple.Create(lib, lib.RuntimeAssemblyGroups.FirstOrDefault(libGroup => compatibleRuntimes.Contains(libGroup.Runtime))))
                .Where(tuple => tuple.Item2?.AssetPaths != null)
                .SelectMany(tuple => tuple.Item2.AssetPaths.Where(x => x != null).Select(path => Tuple.Create(Path.GetFileNameWithoutExtension(path), Tuple.Create(tuple.Item1, tuple.Item2))))
                .ToDictionaryIgnoringDuplicateKeys(tuple => tuple.Item1, tuple => tuple.Item2, StringComparer.OrdinalIgnoreCase);

            if (internalDiagnosticsMessageSink != null)
            {
                internalDiagnosticsMessageSink.OnMessage(new DiagnosticMessage($"[NetCoreAssemblyDependencyResolver..ctor] Managed assembly map includes: {string.Join(",", managedAssemblyMap.Keys.Select(k => $"'{k}'").OrderBy(k => k, StringComparer.OrdinalIgnoreCase))}"));
            }

            unmanagedAssemblyCache = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
            unmanagedAssemblyMap   =
                dependencyContext.RuntimeLibraries
                .Where(lib => lib.NativeLibraryGroups?.Count > 0)
                .Select(lib => Tuple.Create(lib, lib.NativeLibraryGroups.FirstOrDefault(libGroup => compatibleRuntimes.Contains(libGroup.Runtime))))
                .Where(tuple => tuple.Item2?.AssetPaths != null)
                .SelectMany(tuple => tuple.Item2.AssetPaths.Where(x => x != null).Select(path => Tuple.Create(Path.GetFileName(path), Tuple.Create(tuple.Item1, tuple.Item2))))
                .ToDictionaryIgnoringDuplicateKeys(tuple => tuple.Item1, tuple => tuple.Item2, StringComparer.OrdinalIgnoreCase);

            if (internalDiagnosticsMessageSink != null)
            {
                internalDiagnosticsMessageSink.OnMessage(new DiagnosticMessage($"[NetCoreAssemblyDependencyResolver..ctor] Unmanaged assembly map includes: {string.Join(",", unmanagedAssemblyMap.Keys.Select(k => $"'{k}'").OrderBy(k => k, StringComparer.OrdinalIgnoreCase))}"));
            }

            Default.Resolving += OnResolving;
        }
예제 #2
0
        public DependencyContextAssemblyCache(string assemblyFolder,
                                              DependencyContext dependencyContext,
                                              IMessageSink internalDiagnosticsMessageSink,
                                              Platform?operatingSystemPlatform = null,
                                              string currentRuntimeIdentifier  = null,
                                              IFileSystem fileSystem           = null)
        {
            this.assemblyFolder    = assemblyFolder;
            this.dependencyContext = dependencyContext;
            this.internalDiagnosticsMessageSink = internalDiagnosticsMessageSink;
            this.operatingSystemPlatform        = operatingSystemPlatform ?? RuntimeEnvironment.OperatingSystemPlatform;
            this.currentRuntimeIdentifier       = currentRuntimeIdentifier ?? RuntimeEnvironment.GetRuntimeIdentifier();
            this.fileSystem = fileSystem ?? new FileSystemWrapper();

            fallbackRuntimeIdentifier = new Lazy <string>(() => GetFallbackRuntime(this.currentRuntimeIdentifier));
            assemblyResolver          = new XunitPackageCompilationAssemblyResolver(internalDiagnosticsMessageSink, fileSystem);

            if (internalDiagnosticsMessageSink != null)
            {
                internalDiagnosticsMessageSink.OnMessage(new _DiagnosticMessage($"[DependencyContextAssemblyCache..ctor] Runtime graph: [{string.Join(",", dependencyContext.RuntimeGraph.Select(x => $"'{x.Runtime}'"))}]"));
            }

            var compatibleRuntimes = GetCompatibleRuntimes(dependencyContext);

            if (internalDiagnosticsMessageSink != null)
            {
                internalDiagnosticsMessageSink.OnMessage(new _DiagnosticMessage($"[DependencyContextAssemblyCache..ctor] Compatible runtimes: [{string.Join(",", compatibleRuntimes.Select(x => $"'{x}'"))}]"));
            }

            managedAssemblyCache = new ConcurrentDictionary <string, Assembly>(StringComparer.OrdinalIgnoreCase);
            managedAssemblyMap   =
                dependencyContext.RuntimeLibraries
                .Where(lib => lib.RuntimeAssemblyGroups?.Count > 0)
                .Select(lib => compatibleRuntimes.Select(runtime => Tuple.Create(lib, lib.RuntimeAssemblyGroups.FirstOrDefault(libGroup => string.Equals(libGroup.Runtime, runtime))))
                        .FirstOrDefault(tuple => tuple.Item2?.AssetPaths != null))
                .Where(tuple => tuple != null)
                .SelectMany(tuple => tuple.Item2.AssetPaths.Where(x => x != null)
                            .Select(path => Tuple.Create(Path.GetFileNameWithoutExtension(path), Tuple.Create(tuple.Item1, tuple.Item2))))
                .ToDictionaryIgnoringDuplicateKeys(tuple => tuple.Item1, tuple => tuple.Item2, StringComparer.OrdinalIgnoreCase);

            if (internalDiagnosticsMessageSink != null)
            {
                internalDiagnosticsMessageSink.OnMessage(new _DiagnosticMessage($"[DependencyContextAssemblyCache..ctor] Managed assembly map: [{string.Join(",", managedAssemblyMap.Keys.Select(k => $"'{k}'").OrderBy(k => k, StringComparer.OrdinalIgnoreCase))}]"));
            }

            unmanagedDllFormats    = GetUnmanagedDllFormats().ToArray();
            unmanagedAssemblyCache = new ConcurrentDictionary <string, string>(StringComparer.OrdinalIgnoreCase);
            unmanagedAssemblyMap   =
                dependencyContext.RuntimeLibraries
                .Select(lib => compatibleRuntimes.Select(runtime => Tuple.Create(lib, lib.NativeLibraryGroups.FirstOrDefault(libGroup => string.Equals(libGroup.Runtime, runtime))))
                        .FirstOrDefault(tuple => tuple.Item2?.AssetPaths != null))
                .Where(tuple => tuple != null)
                .SelectMany(tuple => tuple.Item2.AssetPaths.Where(x => x != null)
                            .Select(path => Tuple.Create(Path.GetFileName(path), Tuple.Create(tuple.Item1, tuple.Item2))))
                .ToDictionaryIgnoringDuplicateKeys(tuple => tuple.Item1, tuple => tuple.Item2, StringComparer.OrdinalIgnoreCase);

            if (internalDiagnosticsMessageSink != null)
            {
                internalDiagnosticsMessageSink.OnMessage(new _DiagnosticMessage($"[DependencyContextAssemblyCache..ctor] Unmanaged assembly map: [{string.Join(",", unmanagedAssemblyMap.Keys.Select(k => $"'{k}'").OrderBy(k => k, StringComparer.OrdinalIgnoreCase))}]"));
            }
        }