.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中复制注入上百次,虽然能解决问题, ...
随机推荐
- docker相关概念介绍
关键词:docker容器与docker镜像 他们之间的关系是docker容器通过docker镜像来创建 docker镜像就是些像ubuntu15.10,ubuntu14.2一样的系统 docker容器 ...
- 网络游戏开发-客户端2(自定义websocket协议格式)
Egret官方提供了一个Websocket的库,可以让我们方便的和服务器长连接交互. 标题写的时候自定义websocket的协议格式.解释一下,不是说我们去动websocket本身的东西,我们是在we ...
- 详述Python序列化
一.前言 1. 现实需求 每种编程语言都有各自的数据类型,其中面向对象的编程语言还允许开发者自定义数据类型(如:自定义类),Python也是一样.很多时候我们会有这样的需求: 把内存中的各种数据类型的 ...
- bugku 程序员本地网站
提示从本地访问,怎样让服务器认为你是从本地进行访问的: 使用burp抓包并在包中进行修改加入X-Forwarded-For: 127.0.0.1 X-Forwarded-For: 简称XFF头,它代表 ...
- icon font在sketch中的下载与安装
icon font的下载安装: 1.首先打开sketch--插件--管理插件--获取插件--搜索 icon font--点击icon font--clone or download--下载的是一个sk ...
- 决策树算法系列之一 ID3
1 什么是决策树 通俗来说,决策树分类的思想类似于找对象 一个女孩的母亲要给这个女孩介绍男朋友 (分类问题.见或不见) 女孩有自己的一套标准 长相 收入 职业 见面与否 丑 高 某箭队经理 不见 中等 ...
- unittest生成测试报告
1.先导入HTMLTestRunner模块 2.实例一脚本如下 #coding=utf-8 import unittest import HTMLTestRunner #封装批量执行用例 def al ...
- Cocos2d-x 学习笔记(7) 内存管理 Sprite SpriteFrame Texture2D
1. 总结 Sprite和SpriteFrame和Texture2D关系紧密,三个类都继承了Ref类.精灵有成员精灵帧和纹理,精灵帧有成员纹理.精灵帧和纹理被精灵帧引用时,引用计数增加,不再被引用时, ...
- 为什么重写equals必须重写hoshCode的基础分析
为什么重写equals必须重写hoshCode的基础分析 1.我们先来了解下原生的equals和hashCode代码 原生equals:它判断的是两个对象是否相等 原生hashCode值:它是根据内存 ...
- git clone下代码window与unix换行问题
项目中避免不了会写一些shell脚本,使用ln软连接到一个目录.当git clone到windows中,ln连接显示无比怪异(如../xx),打开.sh文件后(仅仅是打开了),git status会看 ...