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

  • 本篇主要讲如何去实现,下一篇主要讲如何把它集成到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. CSS弹性盒子的基本用法

    .container { width: 302px; height: 302px; border: 1px solid; display: flex } .item { width: 100px; h ...

  2. vue中keep-alive的用法

    1.keep-alive的作用以及好处 在做电商有关的项目中,当我们第一次进入列表页需要请求一下数据,当我从列表页进入详情页,详情页不缓存也需要请求下数据,然后返回列表页,这时候我们使用keep-al ...

  3. java多线程对CountDownLatch的使用实例

    介绍 CountDownLatch是一个同步辅助类,它允许一个或多个线程一直等待直到其他线程执行完毕才开始执行. 用给定的计数初始化CountDownLatch,其含义是要被等待执行完的线程个数. 每 ...

  4. mysql SQL Layer各个模块介绍

    https://blog.csdn.net/cymm_liu/article/details/45821929

  5. 调用约定__cdecl __fastcall与__stdcall

    __cdecl __fastcall与__stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数弹出栈,3)以 ...

  6. Windows下安装配置go

    基于 go 1.9.2 + liteIDE + windows10 先安装 go 安装包,作用如同安装框架. 默认安装路径是 C:\Go,通常都会更改,但这会影响到后面设置环境变量,因此更改到哪里请记 ...

  7. 常见性能优化策略的总结 good

    阅读目录 代码 数据库 缓存 异步 NoSQL JVM调优 多线程与分布式 度量系统(监控.报警.服务依赖管理) 案例一:商家与控制区关系的刷新job 案例二:POI缓存设计与实现 案例三:业务运营后 ...

  8. web页面测试

    一.Web的功能测试   1.超链接测试     a.链接与链接的说明文字要匹配 (注:也可以是图片)        b.链接的文字要描述正确        c.链接的文字要精简有效     d.链接 ...

  9. 《javascript语言精粹》读书笔记 Item2 对象

    第三章 对象 JavaScript的简单数据类型包括数字.字符串.布尔值(true和false).null值和undefined值.其他 数字.字符串和布尔值"貌似"对象,因为它们 ...

  10. C. Liebig's Barrels

    You have m = n·k wooden staves. The i-th stave has length ai. You have to assemble nbarrels consisti ...