当前位置: 移动技术网 > IT编程>开发语言>.net > ASP.NET MVC实现依赖注入的完整过程

ASP.NET MVC实现依赖注入的完整过程

2020年03月09日  | 移动技术网IT编程  | 我要评论

湖北蔬菜网,李学庆个人资料,生辰八字取名字

前言

在java的spring中有自动注入功能,使得代码变得更加简洁灵活,所以想把这个功能移植到c#中,接下来逐步分析实现过程

1.使用自动注入场景分析

在asp.net mvc中,无论是什么代码逻辑分层,最终的表现层为controller层,所以我们注入点就是在controller中,这里我们需要替换默认的controllerfactory,扫描代码中标记需要注入的对象,进行实例化注入

public class fastcontrollerfactory : defaultcontrollerfactory
  {
    public override icontroller createcontroller(requestcontext requestcontext, string controllername)
    {
      type type = this.getcontrollertype(requestcontext, controllername);
      object obj = getcontrollerinstance(requestcontext, type);

      //controller中标记autowired属性的自动注入
      list<fieldinfo> autowiredfieldlist = type.getruntimefields().where(f => f.getcustomattribute(typeof(autowired)) != null).tolist();
      foreach (fieldinfo field in autowiredfieldlist)
      {
        field.setvalue(obj, injectutil.container.resolve(field.fieldtype));
      }
      return obj as icontroller;
    }
  }

fastcontrollerfactory就是我们自定义的一个controller工厂,重写createcontroller方法,对标记了autowired这个自定义注解的变量,从bean容器中取出实例进行赋值,同时我们还需要在global文件中的start方法中,进行默认工厂进行替换

controllerbuilder.current.setcontrollerfactory(new fastcontrollerfactory());

2.ioc容器的实现

c#中的自定义容器有很多开源成熟的框架,例如autofac等,这里我们是自己实现一个轻量级的版本

源码地址:https://gitee.com/grassprogramming/fastioc

这里就重点说一下如何在asp.net mvc中的使用,首先我们需要对需要注入的bean对象进行标记,这个标记就叫做component,

在asp.net mvc global文件中的start方法中,我们需要将整个项目中需要自动注入的bean加入到容器中

public class injectutil
  {
    public static containerbuilder container;
    public static void init()
    {
      container = new containerbuilder();
       //获取所有程序集
      var assemblies = system.web.compilation.buildmanager.getreferencedassemblies().cast<assembly>().toarray();
      //注入所有component组件
      container.registerassemblytypes(assemblies, typeof(component),true);
      container.build();
    }
  }

到这里controller层面的事项就已经完成了,接下来就需要在ioc容器中初始化bean实例方法中进一步处理

private object getinstance(registerentity entity)
    {
      object obj = null;
      if (entity.isenableintercept)
      {
        bool isextend = entity.realtype == entity.registtype;
        obj = dynamictproxy.createproxyobject(entity.realtype, entity.registtype, entity.intercepttype, isextend, entity.isinterceptallmethod);


      }
      else
      {
        var constructors = entity.registtype.getconstructors();
        obj = constructors[0].invoke(new object[] { });
      }
      //这里使用单例模式将实例化instance存储,提前暴露未进行后续设置的对象实例
      if (!singleinstancedic.containskey(entity.realtype))
      {
        singleinstancedic.add(entity.realtype, obj);
      }
    
      //如果这个class标记了component,且有标记了autowired的field,进行自动注入
      if (entity.realtype.getcustomattribute(typeof(component), true) != null)
      {
        //这里要使用getruntimefields,此方法返回在指定类型上定义的所有字段,包括继承,非公共,实例和静态字段。
        foreach (fieldinfo field in entity.realtype.getruntimefields())
        {
          if (field.getcustomattribute(typeof(autowired), true) != null)
          {
            type fieldtype = field.fieldtype;
            if (contains(fieldtype))
            {
              //判断单例存储中是否包含,如果有,取出赋值,这里可以防止循环依赖导致的死循环
              if (singleinstancedic.containskey(fieldtype))
              {
                field.setvalue(obj, singleinstancedic[fieldtype]);
              }
              else
              {
                field.setvalue(obj, resolve(fieldtype));
              }
              
            }
          }
        }
      }
      return obj;

    }

getinstance方法就是实例化bean对象的核心方法,其实很简单,就是通过反射创建对象,其中需要注意的有两点

1)对于一个bean初始化时需要扫描bean中的所有变量,如果内部还有依赖注入的嵌套对象,需要使用递归,直到没有需要注入的field

2)我这里使用的是单例模式,因为在测试过程中可能存在在a类中对b进行依赖注入,在b类中对a进行依赖注入,常规创建过程,如果使用递归进行扫描,就会进入死循环,内存溢出,所以使用对象的单例,一旦创建就放入字典中,如果再次扫描到该对象需要注入,则直接取出使用,就避免了循环引用

3.其他

对其他不在controller中使用的类需要依赖注入,则需要直接从ioc的bean容器取出使用

 private authutil @authutil = injectutil.container.resolve<authutil>();

功能到这里就全部分析完毕了,最后打个广告,自己写的asp.net mvc快速开发框架,希望支持一波

地址:https://gitee.com/grassprogramming/fastexecutor

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对移动技术网的支持。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网