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

  • 本篇主要讲如何去实现,下一篇主要讲如何把它集成到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. 重温《STL源码剖析》笔记 第五章

    源码之前,了无秘密  ——侯杰 序列式容器 关联式容器 array(build in) RB-tree vector set heap   map priority-queue multiset li ...

  2. python访问mysql

    1,下载mysql-connector-python-2.0.4  pythoin访问mysql需要有客户端,这个就是连接mysql的库 解压后如下图: 双击lib 以windows为例 把mysql ...

  3. RNN(Recurrent Neural Network)的几个难点

    1. vanish of gradient RNN的error相对于某个时间点t的梯度为: \(\frac{\partial E_t}{\partial W}=\sum_{k=1}^{t}\frac{ ...

  4. @EnableWebMVC注解理解

    @EnableWebMVC注解用来开启Web MVC的配置支持.也就是写Spring MVC时的时候会用到.

  5. Python基本类常用方法

    数学函数 abs(x) 返回数字的绝对值,如abs(-10) 返回 10 ceil(x) 返回数字的上入整数,如math.ceil(4.1) 返回 5 cmp(x, y)如果 x < y 返回 ...

  6. Spring Security4.1.3实现拦截登录后向登录页面跳转方式(redirect或forward)返回被拦截界面

    一.看下内部原理 简化后的认证过程分为7步: 用户访问网站,打开了一个链接(origin url). 请求发送给服务器,服务器判断用户请求了受保护的资源. 由于用户没有登录,服务器重定向到登录页面 填 ...

  7. elementui左侧菜单栏刷新后还是原来的状态

    <template> <div id="leftMenuList"> <el-row> <el-col :span="24&qu ...

  8. 玩转PHP(二)--PHP强大的时间函数:date()

    PHP具有相对来说强大的时间函数date(),该方法有下列一系列参数: 例如: echo date("Y-m-d H:i:s"); //2015-01-09 13:03:30 如果 ...

  9. Java 学习笔记 (一) If 语句

    接触到的教程中if语句所包含boolean表达式都是以数字作为举例,所以误以为string类型的值也可以这样判断,结果发现下面的脚本不工作: String sysTitle = driver.getT ...

  10. 一个简单的例子实现自己的AOP

    AOP是Aspect Oriented Programming的缩写,意思是面向切面编程,与OOP(Object Oriented Programming)面向对象编程对等,都是一种编程思想. 从OO ...