首页 > 解决方案 > 使用 net core 3 MVC 在运行时加载程序集和视图

问题描述

你好吗?我来找你帮忙。

我告诉你我有一个用 asp net core 3 开发的 MVC web 应用程序。

我有一个基本的 MVC Web 应用程序,它包含区域并处理用户管理应用程序、权限等的基本功能。

现在我想为特定功能添加一个新区域,在这种情况下是客户管理。我不想要的是直接向基础项目添加一个区域。

我想要的是动态加载 dll 文件和视图,以保持功能分开,如果一个失败,另一个继续工作。

实现加载 DLL 的功能,这确实有效,因为我使用 web api 对其进行了测试。

但是我找不到加载区域视图的方法,我用 MVC 5 Net Framework 做了一些,尝试传递功能,显然类不一样。你可以帮我解决这个问题。

非常感谢您提前。

代码下方:

插件扩展.cs

public static class PluginExtensions
{

    public static IMvcBuilder AddExtensions(this IMvcBuilder mvc)
    {
        var serviceProvider = mvc.Services.BuildServiceProvider();
        var configuration = serviceProvider.GetService<IConfiguration>();
        var hostingEnvironment = serviceProvider.GetService<IWebHostEnvironment>();
        var logger = serviceProvider.GetService<ILoggerFactory>().CreateLogger<Startup>();
        List<string> extensionDirectories = EnumerateExtensionDirectories(serviceProvider).ToList();
        List<string> searchPatternList = new List<string>
        {
            "*Extension.Mvc*.dll"
        };
        mvc.ConfigureApplicationPartManager(apm =>
        {
            List<string> extensionAssemblies = new List<string>();
            foreach (var extensionDirectory in extensionDirectories)
            {
                for (int i = 0; i < searchPatternList.Count; i++)
                {
                    List<string> tempList = EnumerateExtensionAssemblies(extensionDirectory, searchPatternList[i]).ToList();
                    if (tempList != null && tempList.Count > 0)
                        extensionAssemblies.AddRange(tempList);
                }//for(int i=0;i< searchPatternList.Count; i++)
            }//foreach (var extensionDirectory in extensionDirectories)
            foreach (var extensionAssembly in extensionAssemblies)
            {
                if (TryLoadExtensionAssembly(serviceProvider, extensionAssembly, out var assembly))
                {
                    //logger.Log(AbortAction.Layer.Infrastructure().Meta(new { extensionAssembly = new { extensionAssembly.FullName } }));
                    apm.ApplicationParts.Add(new AssemblyPart(assembly));
                }// if (TryLoadExtensionAssembly(serviceProvider, extensionAssembly, out var assembly))
            }// foreach (var extensionAssembly in extensionAssemblies)


        });

        if (hostingEnvironment.IsProduction() || hostingEnvironment.IsDevelopment())
        {
            ConfigureAssemblyResolve(serviceProvider);
        }
        return mvc;
    }

    private static IEnumerable<string> EnumerateExtensionAssemblies(IServiceProvider serviceProvider)
    {
        var configuration = serviceProvider.GetService<IConfiguration>();
        var hostingEnvironment = serviceProvider.GetService<IWebHostEnvironment>();

        var extRootPath = Path.Combine(hostingEnvironment.ContentRootPath, configuration["Extensibility:Ext"]);
        if (!Directory.Exists(extRootPath)) return new List<string>();
        return Directory.EnumerateFiles(extRootPath, "*Extension.Mvc*.dll");
    }
    private static IEnumerable<string> EnumerateExtensionAssemblies(string assembliesDirectory, string searchPattern)
    {
        if (!Directory.Exists(assembliesDirectory)) return new List<string>();
        return Directory.EnumerateFiles(assembliesDirectory, searchPattern);
    }
    private static IEnumerable<string> EnumerateExtensionDirectories(IServiceProvider serviceProvider)
    {
        var configuration = serviceProvider.GetService<IConfiguration>();
        var hostingEnvironment = serviceProvider.GetService<IWebHostEnvironment>();

        var extRootPath = Path.Combine(hostingEnvironment.ContentRootPath, configuration["Extensibility:Ext"]);
        if (!Directory.Exists(extRootPath)) return new List<string>();
        return Directory.EnumerateDirectories(extRootPath);
    }
    private static bool TryLoadExtensionAssembly(IServiceProvider serviceProvider, string extensionAssembly, out Assembly assembly)
    {

        //extensionAssembly
        try
        {
            if (File.Exists(extensionAssembly))
            {
                assembly = Assembly.LoadFile(extensionAssembly);
                return true;
            }
        }
        catch (Exception ex)
        {
            // logger.Log(Abstraction.Layer.Infrastructure().Routine(nameof(TryLoadExtensionAssembly)).Faulted(), ex);
        }

        assembly = default;
        return false;
    }
    private static void ConfigureAssemblyResolve(IServiceProvider serviceProvider)
    {
        var configuration = serviceProvider.GetService<IConfiguration>();
        var hostingEnvironment = serviceProvider.GetService<IWebHostEnvironment>();
        var logger = serviceProvider.GetService<ILoggerFactory>().CreateLogger<Startup>();
        List<string> extensionDirectories = EnumerateExtensionDirectories(serviceProvider).ToList();
        List<string> extensionAssemblies = new List<string>();
        List<string> searchPatternList = new List<string>
        {
            "*Extension.Entities*.dll",
            "*Extension.Libs*.dll",
            "*Extension.Data*.dll",
            "*Extension.Application*.dll",
            "*Extension.UtilsConnectors*.dll"
        };
        foreach (var extensionDirectory in extensionDirectories)
        {
            for (int i = 0; i < searchPatternList.Count; i++)
            {
                List<string> assembliesReferenceList = EnumerateExtensionAssemblies(extensionDirectory, searchPatternList[i]).ToList();
                if (assembliesReferenceList != null && assembliesReferenceList.Count > 0)
                    foreach (var assemblyReference in assembliesReferenceList)
                    {
                        AppDomain.CurrentDomain.AssemblyResolve += (sender, e) =>
                        {
                            return
                                File.Exists(assemblyReference)
                                    ? Assembly.LoadFile(assemblyReference)
                                    : null;
                        };// AppDomain.CurrentDomain.AssemblyResolve += (sender, e) =>
                    }//foreach (var assemblyReference in assembliesReferenceList)
            }// for (int i = 0; i < searchPatternList.Count; i++)
        }//foreach (var extensionDirectory in extensionDirectories)
    }
}
public static class HostingEnvironmentExtensions
{
    public static bool IsDevelopmentExt(this IWebHostEnvironment hostingEnvironment)
    {
        return hostingEnvironment.IsEnvironment("DevelopmentExt");
    }
}

启动.cs

 public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddMvc(options =>
        {
            options.Filters.Add(new SessionExpireAttribute());
        }).AddExtensions();
        ...
    }

正如你所看到的,我加载了 dll 文件,这是可行的。

后来我将文件(dll和视图(html))复制到我的基础项目的区域文件夹中

在此处输入图像描述

我所在地区的 DLL

在此处输入图像描述

终于看到我所在的地区了

在此处输入图像描述

结果

在此处输入图像描述

最后在项目类型扩展的startup.cs文件中。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
       ... 
       app.UseEndpoints(endpoints =>
        {
            endpoints.MapAreaControllerRoute(
           name: "AreaMyArea",
           areaName: "MyArea",
           pattern: "MyArea/{controller=MYHome}/{action=Index}/{id?}");
            endpoints.MapControllerRoute(
              name: "defaultMA",
              pattern: "{controller=MyExtHome}/{action=Index}/{id?}");

        });
    }

抱歉,此信息的广泛性。你能帮助我吗?。我尽量说清楚。非常感谢你,祝你有美好的一天。

标签: c#asp.net-core-mvcrazor-pages

解决方案


推荐阅读