.netcore之DI批量注入(支持泛型) - xms
一旦系统内模块比较多,按DI标准方法去逐个硬敲AddScoped/AddSingleton/AddTransient缺乏灵活性且效率低下,所以批量注入提供了很大的便捷性,特别是对于泛型的服务类,下面介绍一下我在xms系统中应用的DI便捷工具:
1. 先来个dll助手
无外部依赖,可直接复用
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Loader; namespace Xms.Infrastructure.Utility
{
public class AssemblyHelper
{
public static List<Assembly> GetAssemblies(string searchPattern = "")
{
List<Assembly> assemblies = new List<Assembly>();
if (searchPattern.HasValue())
{
DirectoryInfo root = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
foreach (FileInfo f in root.GetFiles(searchPattern))
{
assemblies.Add(AssemblyLoadContext.Default.LoadFromAssemblyPath(f.FullName));
}
}
else
{
assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies());
}
return assemblies;
} public static List<Type> GetClassOfType(Type assignTypeFrom, string searchPattern = "")
{
var assemblies = GetAssemblies(searchPattern);
var result = new List<Type>();
try
{
foreach (var a in assemblies)
{
Type[] types = a.GetTypes(); if (types == null)
{
continue;
} foreach (var t in types)
{
if (!assignTypeFrom.IsAssignableFrom(t) && (!assignTypeFrom.IsGenericTypeDefinition || !DoesTypeImplementOpenGeneric(t, assignTypeFrom)))
{
continue;
} if (t.IsInterface)
{
continue;
} if (t.IsAbstract)
{
continue;
} result.Add(t);
}
}
}
catch (ReflectionTypeLoadException ex)
{
var msg = string.Empty;
foreach (var e in ex.LoaderExceptions)
{
msg += e.Message + Environment.NewLine;
} var fail = new Exception(msg, ex);
Debug.WriteLine(fail.Message, fail); throw fail;
} return result;
} public static bool DoesTypeImplementOpenGeneric(Type type, Type openGeneric)
{
try
{
var genericTypeDefinition = openGeneric.GetGenericTypeDefinition();
foreach (var implementedInterface in type.FindInterfaces((objType, objCriteria) => true, null))
{
if (!implementedInterface.IsGenericType)
{
continue;
} var isMatch = genericTypeDefinition.IsAssignableFrom(implementedInterface.GetGenericTypeDefinition());
return isMatch;
} return false;
}
catch
{
return false;
}
}
}
}
2. 服务自动注册接口
用于每个模块注册自己的服务,达到模块的高度自治的目的
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; namespace Xms.Infrastructure.Inject
{
/// <summary>
/// 服务自动注册接口
/// </summary>
public interface IServiceRegistrar
{
void Add(IServiceCollection services, IConfiguration configuration); int Order { get; }
}
}
3. DI服务扩展方法
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using Xms.Infrastructure.Inject;
using Xms.Infrastructure.Utility; namespace Xms.Core
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection RegisterAll(this IServiceCollection services, IConfiguration configuration)
{
var types = AssemblyHelper.GetClassOfType(typeof(IServiceRegistrar), "Xms.*.dll");
foreach (var t in types)
{
var instance = (IServiceRegistrar)Activator.CreateInstance(t);
instance.Add(services, configuration);
}
return services;
} public static IServiceCollection RegisterScope<TService>(this IServiceCollection services)
{
var serviceType = typeof(TService);
return Register(services, serviceType, ServiceLifetime.Scoped);
} public static IServiceCollection RegisterScope(this IServiceCollection services, Type serviceType)
{
return Register(services, serviceType, ServiceLifetime.Scoped);
} public static IServiceCollection Register(this IServiceCollection services, Type serviceType, ServiceLifetime serviceLifetime)
{
var implementTypes = AssemblyHelper.GetClassOfType(serviceType, "Xms.*.dll");
if (serviceType.IsGenericType)
{
foreach (var impl in implementTypes)
{
var it = impl.FindInterfaces((type, criteria) =>
{
var isMatch = type.IsGenericType && ((Type)criteria).IsAssignableFrom(type.GetGenericTypeDefinition());
return isMatch;
}, serviceType);
foreach (var i in it)
{
services.Add(new ServiceDescriptor(i, impl, serviceLifetime));
}
}
}
else
{
foreach (var impl in implementTypes)
{
services.Add(new ServiceDescriptor(serviceType, impl, serviceLifetime));
}
}
return services;
}
}
}
4. 使用示例
比如下面的一个事件发布服务类,多个消费者服务类,实现了消费者的动态注册,大大提高了系统的灵活性、扩展性
/// <summary>
/// 事件模块服务注册
/// </summary>
public class ServiceRegistrar : IServiceRegistrar
{
public int Order => ; public void Add(IServiceCollection services, IConfiguration configuration)
{
//event publisher
services.AddScoped<Event.Abstractions.IEventPublisher, Event.EventPublisher>();
//event consumers
services.RegisterScope(typeof(Event.Abstractions.IConsumer<>));
}
}
.netcore之DI批量注入(支持泛型) - xms的更多相关文章
- .netcore利用DI实现订阅者模式 - xms
结合DI,实现发布者与订阅者的解耦,属于本次事务的对象主体不应定义为订阅者,因为订阅者不应与发布者产生任何关联 一.发布者订阅者模式 发布者发出一个事件主题,一个或多个订阅者接收这个事件,中间通过事件 ...
- .NET 使用自带 DI 批量注入服务(Service)和 后台服务(BackgroundService)
今天教大家如何在asp .net core 和 .net 控制台程序中 批量注入服务和 BackgroundService 后台服务 在默认的 .net 项目中如果我们注入一个服务或者后台服务,常规的 ...
- 封装了一些sqlsugar的常用方法 用来动态切换数据库和依赖注入 支持泛型
接口: /// <summary> /// 数据库操作 /// </summary> public interface IDAL_Services { /// <summ ...
- 从我做起[原生DI实现模块化和批量注入].Net Core 之一
实现模块化注册 .Net Core实现模块化批量注入 我将新建一个项目从头开始项目名称Sukt.Core. 该项目分层如下: Sukt.Core.API 为前端提供APi接口(里面尽量不存在业务逻辑, ...
- Spring:(二)DI依赖注入方式
DI 依赖注入 DI(Dependency Injection)依赖注入,说简单一点就将类里面的属性在创建类的过程中给属性赋值,即将对象依赖属性(简单值,集合,对象)通过配置设值给该对象. 属性注入的 ...
- DotNetCore依赖注入实现批量注入
文章转载自平娃子(QQ:273206491):http://os.pingwazi.cn/resource/batchinjectservice 一.依赖注入 通过依赖注入,可以实现接口与实现类的松耦 ...
- AutoFac IoC DI 依赖注入
AutoFac IoC DI 依赖注入 记录点点滴滴知识,为了更好的服务后来者! 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用AutoFac的貌 ...
- Spring-初识Spring框架-IOC控制反转(DI依赖注入)
---恢复内容开始--- IOC :控制反转 (DI:依赖注入)使用ioc模式开发 实体类必须有无参构造方法1.搭建Spring环境下载jarhttp://maven.springframework. ...
- .netCore2.0 程序集DI依赖注入
传统的依赖注入确实简单,但是随着项目的扩展随之而来的问题又来了,因为传统的注入是单个类和接口注入的,加入项目的接口和类增加到了上百个的话,就需要在Startup.cs中复制注入上百次,虽然能解决问题, ...
随机推荐
- 网页布局——Box盒子
在移动端开发的时候,圣杯布局,弹性盒,是我们经常会用得到的,W3C很久以前就有一个display:box属性 flex是最新的,但是在实际的浏览器测试中,display: flex 不能完全替代dis ...
- 微信开发中使用微信JSSDK和使用URL.createObjectURL上传预览图片的不同处理对比
在做微信公众号或者企业微信开发业务应用的时候,我们常常会涉及到图片预览.上传等的处理,往往业务需求不止一张图片,因此相对来说,需要考虑的全面一些,用户还需要对图片进行预览和相应的处理,在开始的时候我使 ...
- NAT模式实现虚拟机共享主机网络
上一节我们在虚拟机上搭建了linux系统,并利用桥接模式访问互联网,这一节,我们来配置一下通过NAT模式访问互联网.说到这里有些小伙伴可能要问了,NAT模式和桥接模式有什么区别呢? 桥接模式: 虚拟机 ...
- 本人亲测-SSM环境搭建(使用eclipse作为示例,过程挺全的,可作为参考)
本人亲测-SSM环境搭建(使用eclipse作为示例,过程挺全的,可作为参考) 本人亲测-SSM环境搭建(使用eclipse作为示例,过程挺全的,可作为参考) 本人亲测-SSM环境搭建(使用eclip ...
- Python爬取猫眼电影100榜并保存到excel表格
首先我们前期要导入的第三方类库有; 通过猫眼电影100榜的源码可以看到很有规律 如: 亦或者是: 根据规律我们可以得到非贪婪的正则表达式 """<div class ...
- Java编程思想——第17章 容器深入研究 读书笔记(一)
这一章将学习散列机制是如何工作的,以及在使用散列容器时怎么样编写hashCode()和equals()方法. 一.容器分类 先上两张图 来概况完整的容器分类 再细说都为什么会有那些特性. 二.填充容器 ...
- Ubuntu 终端中文回显乱码
参考文章 : http://wiki.ubuntu.org.cn/%E4%BF%AE%E6%94%B9locale 所用 Ubuntu的版本 : 猜想是这样的: 1.字符的编码和显示时,所处的环境不是 ...
- comparator接口实现时,只需要实现 int compare(T o1, T o2)方法?
从Comparator接口的源码,可以看到Comparator接口中的方法有三类: 1 普通接口方法 2 default方法 3 static方法 其中default方法和static方法 是java ...
- Libevent::evhttp服务器下载
void http_handler_Get_Download(struct evhttp_request *req, void *arg) { if (req == NULL) { return; } ...
- 我要学并发-Java内存模型到底是什么
内存模型 在计算机CPU,内存,IO三者之间速度差异,为了提高系统性能,对这三者速度进行平衡. CPU 增加了缓存,以均衡与内存的速度差异: 操作系统增加了进程.线程,以分时复用 CPU,进而均衡 C ...