我需要创建一个可扩展的ASP.NET Core 2应用程序。
扩展是一个引用主程序集的项目,可以对其进行扩展,以添加新的控制器,模型(带有EF迁移),视图,剃须刀页面等。
由于扩展需要使用主要应用程序的基本类,例如基本控制器,基本模型或视图/页面布局,因此主要应用程序无法引用模块项目(避免使用循环引用)。
我不确定如何实现此目标,但是这个想法是安装主项目,可以简单地添加模块DLL(或通过在线市场在主应用程序中下载DLL)来添加新功能。
在研究中,我发现了Applications parts,但是这里的问题是我需要在Startup类中指定零件装配体,并且需要在不进行代码任何更改的情况下安装安装模块的能力。
某些模块也需要可扩展,例如会计模块,需要与银行连接,并且它具有定义使用银行的方法的接口,例如:
public interface IBankingOperation
{
public async void PayInvoiceAsync(Invoice invoice);
// More methods...
}
然后,差异项目可以引用银行程序集并为差异银行提供实施。
在主应用程序中,可以像安装其他模块一样安装此模块,但是例如,要检查基本模块是否已安装,我可以像安装其他模块一样安装桑坦德模块,但前提是必须安装银行模块(模块相关性)。
最后,我需要创建一个模块化ASP.NET Core 2应用程序,但是主程序集无法引用模块,模块必须引用主程序集。这些模块可以包含控制器,模型,视图,页面等。
答案 0 :(得分:1)
在主Web应用程序中,您将调用一个将扩展程序加载到内存中的类
ModuleManager.LoadModules(Path.Combine(_env.ContentRootPath, "Modules"));
这是加载模块功能
public static void LoadModules(string modulesFolder)
{
var appsFolders = new DirectoryInfo(modulesFolder).GetDirectories();
foreach (var appFolder in appsFolders)
{
var binFolder = new DirectoryInfo(Path.Combine(appFolder.FullName, "bin"));
if (!binFolder.Exists)
{
continue;
}
var assemblies = AssemblyProvider.GetAssemblies(binFolder.FullName);
foreach (var assembly in assemblies)
{
var iModuleClass = assembly.GetTypes().FirstOrDefault(type => type.GetInterfaces().Contains(typeof(IModule))
&& type.GetConstructor(Type.EmptyTypes) != null);
if (iModuleClass != null)
{
var module = Activator.CreateInstance(iModuleClass) as IModule;
module.ModuleFolder = appFolder;
Modules.Add(module);
Assemblies.Add(assembly);
break;
}
}
}
}
然后,您应该有一个接口,该接口应由每个模块实现,实现此接口的类应完成注册服务和数据库模型以及所有所需人员的工作,并将按以下方式加载它们
public static IEnumerable<IExtensionRegister> GetModuleRegistrars()
{
lock (Modules)
{
return Modules.Select(item => item.Registrar).Where(item=>item!=null).ToList();
}
}