坚持将一些 RC1 代码转换为 RC2

Stuck converting some RC1 code to RC2

在 RC1 中,我可以通过 Librarymanager:

获得 Library 的程序集
_libraryManager.GetLibraries().SelectMany(l => l.Assemblies).Distinct().ToList();

在 RC2 中,似乎没有任何 API 可用于获取库的程序集。

我已阅读公告:https://github.com/aspnet/Announcements/issues/149并且该公告仅说明如何获取程序集的依赖项,并未说明如何获取库的程序集,现在程序集 属性 已弃用。

有人有什么想法吗?

我在这里也提出了一个 github 问题 https://github.com/aspnet/Home/issues/1554

您可以通过以下方式获取程序集:

libManager.GetLibraries()
   .Where(x => x.Identity.Type == LibraryType.Project)
   .Select(x => Assembly.Load(new AssemblyName(x.Identity.Name))).ToList();

这应该获取所有项目引用并加载程序集

从 RC1 到 RC2 的解决方案是放弃 ILibraryManager 并使用新的替代品 (DependencyContext)。在这里查看 MVC6 是如何做到的:

https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/Internal/DefaultAssemblyPartDiscoveryProvider.cs#L55-L158

我也会在这里包含源代码,以防 link 由于某种原因消失:

 // Discovers assemblies that are part of the MVC application using the DependencyContext.
public static class DefaultAssemblyPartDiscoveryProvider
{
    internal static HashSet<string> ReferenceAssemblies { get; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
    {
        "Microsoft.AspNetCore.Mvc",
        "Microsoft.AspNetCore.Mvc.Abstractions",
        "Microsoft.AspNetCore.Mvc.ApiExplorer",
        "Microsoft.AspNetCore.Mvc.Core",
        "Microsoft.AspNetCore.Mvc.Cors",
        "Microsoft.AspNetCore.Mvc.DataAnnotations",
        "Microsoft.AspNetCore.Mvc.Formatters.Json",
        "Microsoft.AspNetCore.Mvc.Formatters.Xml",
        "Microsoft.AspNetCore.Mvc.Localization",
        "Microsoft.AspNetCore.Mvc.Razor",
        "Microsoft.AspNetCore.Mvc.Razor.Host",
        "Microsoft.AspNetCore.Mvc.TagHelpers",
        "Microsoft.AspNetCore.Mvc.ViewFeatures"
    };

    public static IEnumerable<ApplicationPart> DiscoverAssemblyParts(string entryPointAssemblyName)
    {
        var entryAssembly = Assembly.Load(new AssemblyName(entryPointAssemblyName));
        var context = DependencyContext.Load(Assembly.Load(new AssemblyName(entryPointAssemblyName)));

        return GetCandidateAssemblies(entryAssembly, context).Select(p => new AssemblyPart(p));
    }

    internal static IEnumerable<Assembly> GetCandidateAssemblies(Assembly entryAssembly, DependencyContext dependencyContext)
    {
        if (dependencyContext == null)
        {
            // Use the entry assembly as the sole candidate.
            return new[] { entryAssembly };
        }

        return GetCandidateLibraries(dependencyContext)
            .SelectMany(library => library.GetDefaultAssemblyNames(dependencyContext))
            .Select(Assembly.Load);
    }

    // Returns a list of libraries that references the assemblies in <see cref="ReferenceAssemblies"/>.
    // By default it returns all assemblies that reference any of the primary MVC assemblies
    // while ignoring MVC assemblies.
    // Internal for unit testing
    internal static IEnumerable<RuntimeLibrary> GetCandidateLibraries(DependencyContext dependencyContext)
    {
        if (ReferenceAssemblies == null)
        {
            return Enumerable.Empty<RuntimeLibrary>();
        }

        var candidatesResolver = new CandidateResolver(dependencyContext.RuntimeLibraries, ReferenceAssemblies);
        return candidatesResolver.GetCandidates();
    }

    private class CandidateResolver
    {
        private readonly IDictionary<string, Dependency> _dependencies;

        public CandidateResolver(IReadOnlyList<RuntimeLibrary> dependencies, ISet<string> referenceAssemblies)
        {
            _dependencies = dependencies
                .ToDictionary(d => d.Name, d => CreateDependency(d, referenceAssemblies), StringComparer.OrdinalIgnoreCase);
        }

        private Dependency CreateDependency(RuntimeLibrary library, ISet<string> referenceAssemblies)
        {
            var classification = DependencyClassification.Unknown;
            if (referenceAssemblies.Contains(library.Name))
            {
                classification = DependencyClassification.MvcReference;
            }

            return new Dependency(library, classification);
        }

        private DependencyClassification ComputeClassification(string dependency)
        {
            Debug.Assert(_dependencies.ContainsKey(dependency));

            var candidateEntry = _dependencies[dependency];
            if (candidateEntry.Classification != DependencyClassification.Unknown)
            {
                return candidateEntry.Classification;
            }
            else
            {
                var classification = DependencyClassification.NotCandidate;
                foreach (var candidateDependency in candidateEntry.Library.Dependencies)
                {
                    var dependencyClassification = ComputeClassification(candidateDependency.Name);
                    if (dependencyClassification == DependencyClassification.Candidate ||
                        dependencyClassification == DependencyClassification.MvcReference)
                    {
                        classification = DependencyClassification.Candidate;
                        break;
                    }
                }

                candidateEntry.Classification = classification;

                return classification;
            }
        }

        public IEnumerable<RuntimeLibrary> GetCandidates()
        {
            foreach (var dependency in _dependencies)
            {
                if (ComputeClassification(dependency.Key) == DependencyClassification.Candidate)
                {
                    yield return dependency.Value.Library;
                }
            }
        }

        private class Dependency
        {
            public Dependency(RuntimeLibrary library, DependencyClassification classification)
            {
                Library = library;
                Classification = classification;
            }

            public RuntimeLibrary Library { get; }

            public DependencyClassification Classification { get; set; }

            public override string ToString()
            {
                return $"Library: {Library.Name}, Classification: {Classification}";
            }
        }

        private enum DependencyClassification
        {
            Unknown = 0,
            Candidate = 1,
            NotCandidate = 2,
            MvcReference = 3
        }
    }
}