设计一下类似SpringIoC的注入工具~Lind.DI
通过注解(特性)的方式进行对象的注册与注入,方便,灵活!
- 本篇主要讲如何去实现,下一篇主要讲如何把它集成到mvc和api环境里,实现自动的注入!
spring ioc工作的过程大致为,统一的注册组件,拦截当前请求,统一的注入当前请求所需要的组件,事实上,说到这事,.net也完全可以实现这个功能和工作方式,下来大叔来实现一下
- 定义组件注册特性
- 定义组件生命周期
- 定义组件注入特性
- 定义Ioc工厂
- 使用灵活方便
- 将注入功能集成到mvc的拦截器里
定义组件注册特性
定义在类身上
/// <summary>
/// 注册组件特性.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class ComponentAttribute : Attribute
{
public LifeCycle LifeCycle { get; set; } = LifeCycle.CurrentScope;
public String Named { get; set; }
}
定义组件生命周期
/// <summary>
/// 组件生命周期
/// </summary>
public enum LifeCycle
{
CurrentScope,
CurrentRequest,
Global,
}
定义组件注入特性
定义在字段上
/// <summary>
/// 注入一对象.
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
public class InjectionAttribute : Attribute
{
public string Named{get;set;}
}
定义Ioc工厂
/// <summary>
/// DI工厂.
/// </summary>
public class DIFactory
{
static IContainer container;
/// <summary>
/// 手动注入.
/// </summary>
/// <returns>The resolve.</returns>
/// <typeparam name="T">The 1st type parameter.</typeparam>
public static T Resolve<T>()
{
if (container == null)
throw new ArgumentException("please run DIFactory.Init().");
return container.Resolve<T>();
}
/// <summary>
/// 手动注入.
/// </summary>
/// <returns>The by named.</returns>
/// <param name="named">Named.</param>
/// <typeparam name="T">The 1st type parameter.</typeparam>
public static T ResolveByNamed<T>(string named)
{
if (container == null)
throw new ArgumentException("please run DIFactory.Init().");
return container.ResolveNamed<T>(named);
}
/// <summary>
/// 把对象里的Inject特性的对象注入.
/// web环境下,应该使用filter拦截器将当前控制器传传InjectFromObject去注入它.
/// </summary>
/// <param name="obj">Object.</param>
public static void InjectFromObject(object obj)
{
if (obj.GetType().IsClass && obj.GetType() != typeof(string))
foreach (var field in obj.GetType().GetFields(
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public))
{
if (field.GetCustomAttributes(false).Select(i => i.GetType())
.Contains(typeof(InjectionAttribute)))
{
InjectionAttribute inject = (InjectionAttribute)field.GetCustomAttributes(false).FirstOrDefault(i => i.GetType() == typeof(InjectionAttribute));
if (inject != null && !String.IsNullOrWhiteSpace(inject.Named))
{
field.SetValue(obj, container.ResolveNamed(inject.Named, field.FieldType));
}
else
{
field.SetValue(obj, container.Resolve(field.FieldType));
}
//递归处理它的内部字段
InjectFromObject(field.GetValue(obj));
}
}
}
/// <summary>
/// 初始化.
/// </summary>
public static void Init()
{
var builder = new ContainerBuilder();
var arr = AppDomain.CurrentDomain.GetAssemblies().Where(
x => !x.FullName.StartsWith("Dapper")
&& !x.FullName.StartsWith("System")
&& !x.FullName.StartsWith("AspNet")
&& !x.FullName.StartsWith("Microsoft"))
.SelectMany(x => x.DefinedTypes)
.Where(i => i.IsPublic && i.IsClass)
.ToList();
foreach (var type in arr)
{
try
{
if (type.GetCustomAttributes(false).Select(i => i.GetType()).Contains(typeof(ComponentAttribute)))
{
ComponentAttribute componentAttribute = (ComponentAttribute)type.GetCustomAttributes(false).FirstOrDefault(o => o.GetType() == typeof(ComponentAttribute));
if (type.GetInterfaces() != null && type.GetInterfaces().Any())
{
type.GetInterfaces().ToList().ForEach(o =>
{
registor(builder, type, o, componentAttribute);
});
}
else
{
registor(builder, type, type, componentAttribute);
}
}
}
catch (Exception)
{
throw new Exception($"Lind.DI init {type.Name} error.");
}
}
container = builder.Build();
}
/// <summary>
/// 注册组件.
/// </summary>
/// <param name="builder">Builder.</param>
/// <param name="typeImpl">Type impl.</param>
/// <param name="type">Type.</param>
/// <param name="componentAttribute">Component attribute.</param>
static void registor(ContainerBuilder builder, Type typeImpl, Type type, ComponentAttribute componentAttribute)
{
if (componentAttribute.LifeCycle == LifeCycle.Global)
{
if (componentAttribute.Named != null)
builder.RegisterType(typeImpl).Named(componentAttribute.Named, type).SingleInstance();
else
builder.RegisterType(typeImpl).As(type).SingleInstance();
}
else if (componentAttribute.LifeCycle == LifeCycle.CurrentScope)
{
if (componentAttribute.Named != null)
builder.RegisterType(typeImpl).Named(componentAttribute.Named, type).InstancePerLifetimeScope();
else
builder.RegisterType(typeImpl).As(type).InstancePerLifetimeScope();
}
else
{
if (componentAttribute.Named != null)
builder.RegisterType(typeImpl).Named(componentAttribute.Named, type).InstancePerRequest();
else
builder.RegisterType(typeImpl).As(type).InstancePerRequest();
}
}
}
使用灵活方便
支持对象与对象之间的依赖
[Component(Named="RunPeople")]
public class RunPeople : IRun
{
public void Do()
{
System.Console.WriteLine("人类跑起来!");
}
}
[Component]
public class Fly
{
[Injection(Named="RunPeople")]
Run run;
public void step1()
{
run.Do();
System.Console.WriteLine("飞行第一步!");
}
}
使用方式,程序入口先初始化DIFactory.Init();
[Injection]
Fly flyObj;
void print(){
DIFactory.Init();
DIFactory.InjectFromObject(this);
flyObj.step1();
}
static void Main(string[] args)
{
DIFactory.Init();
System.Console.WriteLine("Hello World!");
new Program().print();
}
结果
Hello World!
人类跑起来!
飞行第一步!
设计一下类似SpringIoC的注入工具~Lind.DI的更多相关文章
- 十大关系数据库SQL注入工具一览
摘要:众所周知,SQL注入攻击是最为常见的Web应用程序攻击技术.同时SQL注入攻击所带来的安全破坏也是不可弥补的.以下罗列的10款SQL工具可帮助管理员及时检测存在的漏洞. BSQL Hacker ...
- 10个SQL注入工具(转载)
众所周知,SQL注入攻击是最为常见的Web应用程序攻击技术.同时SQL注入攻击所带来的安全破坏也是不可弥补的.以下罗列的10款SQL注入工具可帮助管理员及时检测存在的漏洞. BSQL Hacker 1 ...
- 10 个 SQL 注入工具
BSQL Hacker BSQL Hacker是由Portcullis实验室开发的,BSQL Hacker 是一个SQL自动注入工具(支持SQL盲注),其设计的目的是希望能对任何的数据库进行SQL溢出 ...
- So注入工具TsoInject开发文档
So注入工具TsoInject开发文档 导语: 作为一个软件安全从业者而言,我们需要对某个App的关键函数就行Hook, 对于android而言,Smali层我们使用Xposed Hook框架,So层 ...
- oracle union 注入工具
'***********************************************************************************************'ora ...
- 详解强大的SQL注入工具——SQLMAP
1. 前言 Windows下的注入工具好的又贵,免费的啊D.明小子等又不好用,我们根本没必要花 时间去找什么破解的havij.pangolin什么的,特别是破解的工具很可能被绑了木马.其实 Linu ...
- 记一次SQL联合查询注入工具的编写
这是一个ASP网站的简单SQL注入检测和利用的工具,主要的功能是简单的检测出SQL注入漏洞,可以使用该id存在的SQL注入来获取数据库中的网站管理员的表名和字段名,猜解数据库中该表的字段数,最后通过联 ...
- sql注入工具:sqlmap命令
sqlmap是一款专业的sql注入工具, 让你告别人工注入, 程序高效自动注入 前提是你有找到注入点 , 工具的官方网站:http://sqlmap.org/ kali系统默认安装sqlmap, 不需 ...
- 如何编写一个SQL注入工具
0x01 前言 一直在思考如何编写一个自动化注入工具,这款工具不用太复杂,但是可以用最简单.最直接的方式来获取数据库信息,根据自定义构造的payload来绕过防护,这样子就可以. 0x02 SQL注 ...
随机推荐
- Download and Install Apache Zookeeper on Ubuntu
http://www.techburps.com/misc/download-and-install-apache-zookeepr/36 In previous article of this Bi ...
- 人脸检测? 对Python来说太简单, 调用dlib包就可以完成
"Dlib 是一个现代化的 C ++ 工具包,包含用于创建复杂软件的机器学习算法和工具 " .它使您能够直接在 Python 中运行许多任务,其中一个例子就是人脸检测. 安装 dl ...
- 循环中else的用法
name = 'hello' for x in name: print(x) if x == 'l': break #退出for循环 else: print("==for循环过程中,如果没有 ...
- Flask入门之Bootstrap介绍使用和Flask-Nav快速导航栏
一.Bootstrap Bootstrap,来自 Twitter,是目前最受欢迎的前端框架. Python中,同样可以使用Bootstrap. 1. 导入Bootstrap库 from flask_b ...
- Redis模糊查询
最近使用Redis优化项目功能,其中有一部分为模糊查询,找了很多帖子,也没有找到很好的解决方案和思路,最终皇天不负有心人啊,终于让我找到了!!! 感谢该帖作者:WalkerAlone 原文链接:ht ...
- 安装SQL Server DQS 和 MDS
tep1: 安装特性时选择Data Quality Services 和 Master Data Services Step2: 安装完成之后, 打开 SQL Server 2017 Data ...
- 进阶-JMS 知识梳理
JMS 一. 概述与介绍 ActiveMQ 是Apache出品,最流行的.功能强大的即时通讯和集成模式的开源服务器.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Pro ...
- sql server 分区(上)
分区发展历程 基于表的分区功能为简化分区表的创建和维护过程提供了灵活性和更好的性能.追溯到逻辑分区表和手动分区表的功能. 二.为什么要进行分区 为了改善大型表以及具有各种访问模式的表的可伸缩 ...
- fatal: HttpRequestException encountered 解决方法
fatal: HttpRequestException encountered解决方法 之前在windows下一段时间git push都没什么问题,最近一旦提交就会弹出 无论是push前先将远程 ...
- 单机配置kafka和zookeeper
1:环境准备 jdk 推荐oracle,不建议open sdk 在/etc/profile加入下列环境变量 在PATH中将jdk和jre的bin加入path里面 $JAVA_HOME/bin:$JRE ...