一旦系统内模块比较多,按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的更多相关文章

  1. .netcore利用DI实现订阅者模式 - xms

    结合DI,实现发布者与订阅者的解耦,属于本次事务的对象主体不应定义为订阅者,因为订阅者不应与发布者产生任何关联 一.发布者订阅者模式 发布者发出一个事件主题,一个或多个订阅者接收这个事件,中间通过事件 ...

  2. .NET 使用自带 DI 批量注入服务(Service)和 后台服务(BackgroundService)

    今天教大家如何在asp .net core 和 .net 控制台程序中 批量注入服务和 BackgroundService 后台服务 在默认的 .net 项目中如果我们注入一个服务或者后台服务,常规的 ...

  3. 封装了一些sqlsugar的常用方法 用来动态切换数据库和依赖注入 支持泛型

    接口: /// <summary> /// 数据库操作 /// </summary> public interface IDAL_Services { /// <summ ...

  4. 从我做起[原生DI实现模块化和批量注入].Net Core 之一

    实现模块化注册 .Net Core实现模块化批量注入 我将新建一个项目从头开始项目名称Sukt.Core. 该项目分层如下: Sukt.Core.API 为前端提供APi接口(里面尽量不存在业务逻辑, ...

  5. Spring:(二)DI依赖注入方式

    DI 依赖注入 DI(Dependency Injection)依赖注入,说简单一点就将类里面的属性在创建类的过程中给属性赋值,即将对象依赖属性(简单值,集合,对象)通过配置设值给该对象. 属性注入的 ...

  6. DotNetCore依赖注入实现批量注入

    文章转载自平娃子(QQ:273206491):http://os.pingwazi.cn/resource/batchinjectservice 一.依赖注入 通过依赖注入,可以实现接口与实现类的松耦 ...

  7. AutoFac IoC DI 依赖注入

    AutoFac IoC DI 依赖注入 记录点点滴滴知识,为了更好的服务后来者! 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用AutoFac的貌 ...

  8. Spring-初识Spring框架-IOC控制反转(DI依赖注入)

    ---恢复内容开始--- IOC :控制反转 (DI:依赖注入)使用ioc模式开发 实体类必须有无参构造方法1.搭建Spring环境下载jarhttp://maven.springframework. ...

  9. .netCore2.0 程序集DI依赖注入

    传统的依赖注入确实简单,但是随着项目的扩展随之而来的问题又来了,因为传统的注入是单个类和接口注入的,加入项目的接口和类增加到了上百个的话,就需要在Startup.cs中复制注入上百次,虽然能解决问题, ...

随机推荐

  1. redis的安装与五种结构的使用

    这次我们来说说我们的redis,在我们的redis的认知里,最熟悉的就是用redis作为缓存使用,还有我们的分布式session,其实还有很多redis的使用,还有redis的哨兵模式等等. Redi ...

  2. 如何编译和调试Python内核源码?

    目录 写在前面 获取源代码 源代码的组织 windows下编译CPython 调试CPython 小结 参考 博客:blog.shinelee.me | 博客园 | CSDN 写在前面 如果对Pyth ...

  3. 2. spring 应用之IOC

    本文是作者原创,版权归作者所有.若要转载,请注明出处 我们知道Spring Framework 最重要的功能就是IoC (Inversion of Control ),也叫DI(dependency ...

  4. LeetCode 第 287 号问题:寻找重复数,一道非常简单的数组遍历题,加上四个条件后感觉无从下手

    今天分享的题目来源于 LeetCode 第 287 号问题:寻找重复数. 题目描述 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个 ...

  5. 实验吧之【拐弯抹角】(url伪静态)

    题目地址:http://ctf5.shiyanbar.com/indirection/ 打开后给了源码 <?php // code by SEC@USTC echo '<html>& ...

  6. 【阿里云IoT+YF3300】6.物联网设备报警配置

    纵然5G时代已经在时代的浪潮中展现出了它的身影,但是就目前的物联网环境中,网络问题仍旧是一个比较突出的硬伤.众所周知,在当前的物联网规划中,与其说是实现万物互联,倒不如说是行业指标数据监控.对于一些特 ...

  7. .htaccess文件上传利用

    一般.htaccess可以用来留后门和针对黑名单绕过 创建一个txt写入 AddType application/x-httpd-php .png 打开另存为 保存类型为所有文件 上传.htacces ...

  8. jmeter-操作mysql

    1.下载mysql驱动并放至如下目录:E:\soft\apache-jmeter-5.1.1\lib\ext 2.添加JDBC Connection Configuration(线程组-配置元件-JD ...

  9. 树莓派上搭建arduino命令行开发环境

    -------------还是博客园上面的格式看这舒服,不去新浪了------------- 为什么要在树莓派上开发arduino呢?总要把树莓派用起来嘛,不然老吃灰. 树莓派使用SSH时没有图形界面 ...

  10. Python 的多线程是鸡肋?

    "唉,还没毕业就受到甲方的支配,等以后进了公司可咋整啊."小白嘴里这么吐槽,但心理上还是不敢怠慢,只能恋恋不舍地关掉眼前的游戏,打开了 Python 代码思考了起来. " ...