0

我正在使用程序集加载上下文在我的主机应用程序中加载插件 Web 应用程序(以前我使用过 AppDomains)


    public class PluginAssemblyLoadContext : AssemblyLoadContext
    {
        private AssemblyDependencyResolver _resolver;
        
        private IDictionary<string, Assembly> _loadedAssemblies;
        
        private IDictionary<string, Assembly> _sharedAssemblies;

        private AssemblyLoadContext DefaultAlc;

        private string _path;

        public PluginAssemblyLoadContext(string path, bool isCollectible, params Type[] sharedTypes)
             : this(path, isCollectible, sharedTypes.Select(t => t.Assembly).ToArray())
        {
        }

        public PluginAssemblyLoadContext(string path, bool isCollectible, params Assembly[] sharedAssemblies)
             : base(isCollectible: isCollectible)
        {

            _path = path;

            DefaultAlc = GetLoadContext(Assembly.GetExecutingAssembly()) ?? Default;

            var fileInfo = new FileInfo(_path);
            if (fileInfo.Exists)
            {
                _resolver = new AssemblyDependencyResolver(_path);

                _sharedAssemblies = new Dictionary<string, Assembly>(StringComparer.OrdinalIgnoreCase);
                foreach (var a in sharedAssemblies.Distinct())
                {
                    LoadReferencedAssemblies(a);
                }

                _loadedAssemblies = new Dictionary<string, Assembly>();

                var assembly = LoadFromAssemblyPath(fileInfo.FullName);

                _loadedAssemblies.Add(fileInfo.FullName, assembly);
            }
            else
            {
                throw new FileNotFoundException($"File does not exist: {_path}");
            }
        }

        public bool LoadReferencedAssemblies(Assembly assembly)
        {
            if (assembly == null)
            {
                throw new ArgumentNullException(nameof(assembly));
            }
            if (string.IsNullOrEmpty(assembly.Location))
            {
                throw new NotSupportedException($"Assembly location is empty string or null: {assembly.FullName}");
            }
            var alc = GetLoadContext(assembly);
            if (alc == this)
            {
                throw new InvalidOperationException($"Circular assembly loader dependency detected");
            }
            if (!_sharedAssemblies.ContainsKey(assembly.Location))
            {
                _sharedAssemblies.Add(assembly.Location, assembly);

                foreach (var an in assembly.GetReferencedAssemblies())
                {
                    var ra = alc.LoadFromAssemblyName(an);
                    LoadReferencedAssemblies(ra);
                }
                return true;
            }
            else
            {
                return false;
            }
        }

        public IEnumerable<Type> GetCommandTypes<T>()
        {
            var cmdType = typeof(T);
            return _loadedAssemblies.Values.SelectMany(a => a.GetTypes()).Where(t => cmdType.IsAssignableFrom(t));
        }

        public IEnumerable<T> CreateCommands<T>(Assembly assembly)
        {
            foreach (var cmdType in GetCommandTypes<T>())
            {
                yield return (T)Activator.CreateInstance(cmdType);
            }
        }

        protected override Assembly Load(AssemblyName assemblyName)
        {
            var path = _resolver.ResolveAssemblyToPath(assemblyName);
            if (path != null)
            {
                if (_sharedAssemblies.ContainsKey(path))
                {
                    return _sharedAssemblies[path];
                }
                if (_loadedAssemblies.ContainsKey(path))
                {
                    return _loadedAssemblies[path];
                }
                return LoadFromAssemblyPath(path);
            }     
            return DefaultAlc.LoadFromAssemblyName(assemblyName);
        }
    }

问题是剃须刀无法正常加载加载视图。

我越来越:



System.ArgumentNullException: Value cannot be null. (Parameter 'item')
   at Microsoft.AspNetCore.Mvc.Razor.Compilation.CompiledViewDescriptor..ctor(RazorCompiledItem item)
   at Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.RuntimeViewCompiler.CompileAndEmit(String relativePath)
   at Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation.RuntimeViewCompiler.OnCacheMiss(String normalizedPath)

我使用了 dnSpy 并检测到视图程序集生成工作正常,但是 RazorCompiledItemLoader.LoadItems(assembly) 给出了 0 个项目,因为 assembly.GetCustomAttributes() 给出了 0 个属性。

但是 RazorCompiledItemAttribute 实际上是存在的!我已经通过 dnSpy 保存了视图程序集并转储到磁盘。当我在 ConfigureServices(IServiceCollection services) 期间尝试在插件内部获取自定义属性时...(例如)我得到 0 个匹配的属性。但是外部插件调用我得到 1 个匹配属性!如何让剃刀加载这个 RazorCompiledItemAttribute?

4

0 回答 0