仿ABP实现模块注入方法
ABP的模块注入非常不错,但是ABP太臃肿了,单独的模块或者功能不能抽出来单独使用,所以就想自己实现一个模块注入方法。
ABP的模块注入原理,是程序启动时扫描所有dll模块,进行批量注入,下面是实现方法。
一、模块抽象类
/// <summary>
/// 模块抽象类
/// </summary>
public abstract class ICoreModule
{
/// <summary>
/// 注册依赖方法
/// </summary>
public abstract void Register();
/// <summary>
/// 环境名称
/// </summary>
public string EnvironmentName
{
get
{
return System.Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
}
}
/// <summary>
/// 是否是开发环境
/// </summary>
public bool IsDevelopment
{
get
{
return this.EnvironmentName == "Development";
}
}
/// <summary>
/// 当前运行程序集名称
/// </summary>
public string CurrentDomainName
{
get
{
//return AppDomain.CurrentDomain.GetType().FullName;
return AppDomain.CurrentDomain.FriendlyName;
}
}
}
二、每个子项目下添加DependencyModule类
namespace Core
{
public class DependencyModule : ICoreModule
{
public override void Register()
{
//可以根据启动项目/项目环境来判断注入,例如单元测试项目
if (this.CurrentDomainName == "UnitTest" || this.IsDevelopment)
{
AutofacFactory.RegisterAssemblyTypes(Assembly.GetExecutingAssembly());
AutofacFactory.RegisterTypeAs(typeof(IAuthContext), typeof(AuthContext));
}
else
{
AutofacFactory.RegisterAssemblyTypes(typeof(BaseRepository<>).Assembly,
x => x.IsClass && !x.IsInterface,
x => x.BaseType.IsGenericType && x.BaseType.GetGenericTypeDefinition() == typeof(BaseRepository<>));
AutofacFactory.RegisterAssemblyTypes(typeof(BaseEs<>).Assembly,
x => x.IsClass && !x.IsInterface,
x => x.BaseType.IsGenericType && x.BaseType.GetGenericTypeDefinition() == typeof(BaseEs<>));
}
}
}
}
namespace ServerApi
{
public class DependencyModule : ICoreModule
{
public override void Register()
{
AutofacFactory.RegisterAssemblyTypes(typeof(Startup).Assembly,
x => x.IsClass && !x.IsInterface,
x => x.BaseType.IsGenericType && x.BaseType.GetGenericTypeDefinition() == typeof(IHandler<>));
}
}
}
三、项目启动时,注入autofac容器
1、.netcore2.1
关键代码 return new AutofacServiceProvider(AutofacExt.InitAutofac(services));
namespace WebApi
{
public class Startup
{
public Startup(IConfiguration configuration, IOptions<AppSetting> appConfiguration)
{
Configuration = configuration;
_appConfiguration = appConfiguration;
}
public IConfiguration Configuration { get; }
public IOptions<AppSetting> _appConfiguration;
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.Configure<AppSetting>(Configuration.GetSection("AppSetting"));
services.AddMvc(config =>
{
config.Filters.Add<BasicFrameFilter>();
})
.AddControllersAsServices()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddMemoryCache();
services.AddCors();
var dbType = ((ConfigurationSection)Configuration.GetSection("AppSetting:DbType")).Value;
if (dbType == Define.DBTYPE_SQLSERVER)
{
services.AddDbContext<BasicFrameDBContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DBContext")));
}
else //mysql
{
services.AddDbContext<BasicFrameDBContext>(options =>
options.UseMySql(Configuration.GetConnectionString("DBContext")));
}
services.AddHttpClient();
return new AutofacServiceProvider(AutofacExt.InitAutofac(services));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(route =>
{
route.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
route.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
});
}
}
}
2、.netcore3.1
关键代码
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
AutofacFactory.InitAutofac(builder);
builder.RegisterBuildCallback(scope =>
{
AutofacFactory.SetContainer((IContainer)scope);
});
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews().AddControllersAsServices();
services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();//修改属性名称的序列化方式,首字母小写
options.SerializerSettings.Converters.Add(new DateTimeConverter());//修改时间的序列化方式
options.SerializerSettings.Converters.Add(new LongConverter());
});
services.AddOptions();
services.AddMemoryCache();
services.AddCors(options => options.AddPolicy("cors", builder => { builder.AllowAnyMethod().SetIsOriginAllowed(_ => true).AllowAnyHeader().AllowCredentials(); }));
services.AddSignalR();
}
//Autofac注册
public void ConfigureContainer(ContainerBuilder builder)
{
AutofacFactory.InitAutofac(builder);
builder.RegisterBuildCallback(scope =>
{
AutofacFactory.SetContainer((IContainer)scope);
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment() || env.IsEnvironment("Debug"))
{
app.UseDeveloperExceptionPage();
}
app.UseCors("cors");
app.UseWebSockets();
//错误拦截中间件
app.UseMiddleware<ExceptionMiddleware>();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<MessageHub>("/MessageHub");
endpoints.Map("/", context =>
{
context.Response.Redirect($"/api/Home/Index");
return Task.CompletedTask;
});
});
}
}
四、AutofacFactory类
public static class AutofacFactory
{
private static IContainer _container;
private static ContainerBuilder _builder;
static AutofacFactory()
{
}
public static IContainer InitAutofac(IServiceCollection services)
{
_builder = new ContainerBuilder();
RegisterAllModule();
if (services.All(u => u.ServiceType != typeof(IHttpContextAccessor)))
{
services.AddScoped(typeof(IHttpContextAccessor), typeof(HttpContextAccessor));
}
_builder.Populate(services);
_container = _builder.Build();
return _container;
}
public static IContainer InitAutofac()
{
_container = _builder.Build();
return _container;
}
public static void InitAutofac(ContainerBuilder builder)
{
_builder = builder;
RegisterAllModule();
}
public static void SetContainer(IContainer container)
{
_container = container;
}
public static IContainer GetContainer()
{
return _container;
}
public static ContainerBuilder GetBuilder()
{
return _builder;
}
public static void RegisterAssemblyTypes(params Assembly[] assemblies)
{
_builder.RegisterAssemblyTypes(assemblies);
}
public static void RegisterAssemblyTypes(Assembly assemblie, params Func<Type, bool>[] predicates)
{
var regBuilder = _builder.RegisterAssemblyTypes(assemblie);
foreach (var pre in predicates)
{
regBuilder.Where(pre);
}
}
public static void RegisterTypeAs(Type iServiceType, Type implementationType, AutofacLifetime lifetime = AutofacLifetime.InstancePerDependency)
{
var regbuilder = _builder.RegisterType(implementationType).As(iServiceType);
if (lifetime == AutofacLifetime.SingleInstance)
{
regbuilder.SingleInstance();
}
else if (lifetime == AutofacLifetime.InstancePerLifetimeScope)
{
regbuilder.InstancePerLifetimeScope();
}
}
public static void RegisterType(Type serviceType, AutofacLifetime lifetime = AutofacLifetime.InstancePerDependency)
{
var regbuilder = _builder.RegisterType(serviceType);
if (lifetime == AutofacLifetime.SingleInstance)
{
regbuilder.SingleInstance();
}
else if (lifetime == AutofacLifetime.InstancePerLifetimeScope)
{
regbuilder.InstancePerLifetimeScope();
}
}
/// <summary>
/// 泛型类型注册
/// </summary>
public static void RegisterGeneric(Type iServiceType, Type implementationType, AutofacLifetime lifetime = AutofacLifetime.InstancePerDependency)
{
var regbuilder = _builder.RegisterGeneric(implementationType).As(iServiceType);
if (lifetime == AutofacLifetime.SingleInstance)
{
regbuilder.SingleInstance();
}
else if (lifetime == AutofacLifetime.InstancePerLifetimeScope)
{
regbuilder.InstancePerLifetimeScope();
}
}
public static void RegisterGeneric(Type serviceType, AutofacLifetime lifetime = AutofacLifetime.InstancePerDependency)
{
var regbuilder = _builder.RegisterGeneric(serviceType);
if (lifetime == AutofacLifetime.SingleInstance)
{
regbuilder.SingleInstance();
}
else if (lifetime == AutofacLifetime.InstancePerLifetimeScope)
{
regbuilder.InstancePerLifetimeScope();
}
}
public static void RegisterType<iserviceType, implementationType>(AutofacLifetime lifetime = AutofacLifetime.InstancePerDependency)
{
var regbuilder = _builder.RegisterType<implementationType>().As<iserviceType>();
if (lifetime == AutofacLifetime.SingleInstance)
{
regbuilder.SingleInstance();
}
else if (lifetime == AutofacLifetime.InstancePerLifetimeScope)
{
regbuilder.InstancePerLifetimeScope();
}
}
public static void Register<serviceType>(object obj, AutofacLifetime lifetime = AutofacLifetime.InstancePerDependency)
{
var regbuilder = _builder.Register(x => obj).As<serviceType>();
if (lifetime == AutofacLifetime.SingleInstance)
regbuilder.SingleInstance();
else if (lifetime == AutofacLifetime.InstancePerLifetimeScope)
regbuilder.InstancePerLifetimeScope();
}
public static T Resolve<T>()
{
return _container.Resolve<T>();
}
public static object Resolve(Type type)
{
return _container.Resolve(type);
}
/// <summary>
/// 注册全部模块
/// </summary>
public static void RegisterAllModule(params string[] dllnames)
{
var assembles = DependencyContext.Default.RuntimeLibraries.Select(x => x);
if (dllnames.Count() > 0)
{
foreach (string dllname in dllnames)
{
assembles = assembles.Where(o => o.Name.StartsWith(dllname));
}
var dlls = assembles.Select(o => Assembly.Load(new AssemblyName(o.Name))).ToArray();
}
else
{
var dlls = assembles.Where(o => o.Type == "project")
.Select(o => Assembly.Load(new AssemblyName(o.Name))).ToArray();
}
//根据抽象类查找
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes().Where(t => t.BaseType == typeof(ICoreModule) && t.BaseType.IsAbstract))
.ToArray();
//根据接口查找
//var types = AppDomain.CurrentDomain.GetAssemblies()
// .SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(ICoreModule))))
// .ToArray();
foreach (var t in types)
{
var instance = (ICoreModule)Activator.CreateInstance(t);
instance.Register();
}
}
}
/// <summary>
/// 生命周期
/// </summary>
public enum AutofacLifetime
{
/// <summary>
/// 默认生命周期,每次请求都创建新的对象
/// </summary>
InstancePerDependency,
/// <summary>
/// 每次都用同一个对象
/// </summary>
SingleInstance,
/// <summary>
/// 同一个Lifetime生成的对象是同一个实例
/// </summary>
InstancePerLifetimeScope
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!