通过注解(特性)的方式进行对象的注册与注入,方便,灵活!

  • 本篇主要讲如何去实现,下一篇主要讲如何把它集成到mvc和api环境里,实现自动的注入!

spring ioc工作的过程大致为,统一的注册组件,拦截当前请求,统一的注入当前请求所需要的组件,事实上,说到这事,.net也完全可以实现这个功能和工作方式,下来大叔来实现一下

  1. 定义组件注册特性
  2. 定义组件生命周期
  3. 定义组件注入特性
  4. 定义Ioc工厂
  5. 使用灵活方便
  6. 将注入功能集成到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的更多相关文章

  1. 十大关系数据库SQL注入工具一览

    摘要:众所周知,SQL注入攻击是最为常见的Web应用程序攻击技术.同时SQL注入攻击所带来的安全破坏也是不可弥补的.以下罗列的10款SQL工具可帮助管理员及时检测存在的漏洞. BSQL Hacker ...

  2. 10个SQL注入工具(转载)

    众所周知,SQL注入攻击是最为常见的Web应用程序攻击技术.同时SQL注入攻击所带来的安全破坏也是不可弥补的.以下罗列的10款SQL注入工具可帮助管理员及时检测存在的漏洞. BSQL Hacker 1 ...

  3. 10 个 SQL 注入工具

    BSQL Hacker BSQL Hacker是由Portcullis实验室开发的,BSQL Hacker 是一个SQL自动注入工具(支持SQL盲注),其设计的目的是希望能对任何的数据库进行SQL溢出 ...

  4. So注入工具TsoInject开发文档

    So注入工具TsoInject开发文档 导语: 作为一个软件安全从业者而言,我们需要对某个App的关键函数就行Hook, 对于android而言,Smali层我们使用Xposed Hook框架,So层 ...

  5. oracle union 注入工具

    '***********************************************************************************************'ora ...

  6. 详解强大的SQL注入工具——SQLMAP

    1. 前言  Windows下的注入工具好的又贵,免费的啊D.明小子等又不好用,我们根本没必要花 时间去找什么破解的havij.pangolin什么的,特别是破解的工具很可能被绑了木马.其实 Linu ...

  7. 记一次SQL联合查询注入工具的编写

    这是一个ASP网站的简单SQL注入检测和利用的工具,主要的功能是简单的检测出SQL注入漏洞,可以使用该id存在的SQL注入来获取数据库中的网站管理员的表名和字段名,猜解数据库中该表的字段数,最后通过联 ...

  8. sql注入工具:sqlmap命令

    sqlmap是一款专业的sql注入工具, 让你告别人工注入, 程序高效自动注入 前提是你有找到注入点 , 工具的官方网站:http://sqlmap.org/ kali系统默认安装sqlmap, 不需 ...

  9. 如何编写一个SQL注入工具

    0x01  前言 一直在思考如何编写一个自动化注入工具,这款工具不用太复杂,但是可以用最简单.最直接的方式来获取数据库信息,根据自定义构造的payload来绕过防护,这样子就可以. 0x02 SQL注 ...

随机推荐

  1. C#学习笔记 day_two

    C#学习笔记 day two Chapter 2 c#基本概念 2.1编译与运行hello world应用程序 点击f5或者vs2010中的运行图标即可 2.3C#的概念拓展 (1)继承性:一个类含有 ...

  2. js实用技巧

    IIFE(立即调用函数表达式)最广泛的用途是避免污染全局作用域. 已经有很多JavaScript库和JavaScript高手正在使用这种技巧, 尤其是在最流行jQuery插件的开发者中. 你也应该把这 ...

  3. [Java算法分析与设计]--顺序栈的实现

    在程序的世界,栈的应用是相当广泛的.其后进先出的特性,我们可以应用到诸如计算.遍历.代码格式校对等各个方面.但是你知道栈的底层是怎么实现的吗?现在跟随本篇文章我们来一睹它的庐山真面目吧. 首先我们先定 ...

  4. CentOS6系列系统启动常见故障排查与解决方法

    情景一.内核文件损坏 /boot/vmlinuz-2.6.32-642.el6.x86_64 内核文件 1.故障现象 2.解决方法:挂载光盘,进入rescue(救援)模式 3.选择--English- ...

  5. 关于css盒模型

    在css中,width和height指的是内容区域的宽度和高度.增加内边距,边框和外边距不会影响内容区域的尺寸,但是会增加元素框的总尺寸.假设框的每个边上有10个像素的外边距和5像素的内边距,如果希望 ...

  6. SSM博客

    最近在写基于SSM 的博客,用的是spring+springmvc+mybatis搭建的,用的maven+github管理项目,目前完成了登录注册以及用户管理员的增删改查,后续的功能还需要完善,如何建 ...

  7. 双网卡+mitmproxy+iptables搭建SSL中间人(支持非HTTPS协议)

    "想要解决一个问题,最根本方法的就是了解这一切是如何工作的,而不是玄学." --ASCII0X03 最近学习发现现在很多现成的安卓SSL中间人工具和教程都只针对HTTPS流量,比如 ...

  8. .NET开发微信小程序-Template模块开发

    1.添加一个文件目录,里面放模板信息 例:我在根目录添加一个文件夹:template 然后在这个文件夹下面添加相应的页面.比如我添加一个promodel.wxml文件.主要是放商品相关的模块信息(注: ...

  9. maven安装和配置及创建maven项目

    (1)下载maven,下载成功后,解压到本地磁盘 里面包含这几项 (2)配置maven环境变量MAVEN_HOME.path (3)最后检验配置是否成功:用win键+R,来打开命令行提示符窗口,即Do ...

  10. SpringMVC中的拦截器

    1. 自定义拦截器 实现HandlerInterceptor接口 拦截器一: package cn.rodge.ssm.interceptor;import javax.servlet.http.Ht ...