实现一个简单的di容器

之前看了好多框架,laravel,thinkphp,yii等等。基本上都使用了容器。对于我而言,虽然看懂了laravel是怎么写的,但是如果自己不去尝试一下,始终觉得不会这个东西。

下面的代码是我实现的一个简单的容器,很多地方处理并不是很好,但是应该已经足够了。

<?php

class Container{
    
    //$binds 这个变量保存,是名字=>实例的映射
    private $binds = [];


    public static $instance = null;

    /**
     * 单例
     */
    public static function getInstance(){
        if(static::$instance == null){
            static::$instance = new static();
            return static::$instance ;
        }
        return static::$instance;
    }

    /**
     * 一开始是受到laravel的影响,所以写了一个bind函数,
     * 看完laravel的容器实现,印象之中,$concrete和$abstract来回变换。
     * 下面的代码有点像thinkphp的里面的实现,好理解一点
     */
    public static function bind($name,$class = null){
        if($class instanceof Closure){
            static::getInstance()->binds[$name] = $class;
        }else if(is_object($class)){
            static::getInstance()->binds[$name] = $class;
        }else{
            //在这里开始make一个数组,laravel好像是make和build分开的。
            static::getInstance()->make($name);
        }
        
    }

    /**
     * 核心是make方法了
     */
    public static function get($name){
        return static::getInstance()->make($name);
    }

    /**
     * 核心make方法
     */
    public function make($name){
        try{
            //根据类名去查找$this->binds实例是否已经存在,如果存在就直接返回
            if(array_key_exists($name,$this->binds)){
                return $this->binds[$name];
            }
            //根据类名得到它的反射类
            $reflectClass = new ReflectionClass($name);
            //利用反射类
            $constructor = $reflectClass->getConstructor();
            //如果没有构造器的话,就直接去实例化它
            $params = [];
            if(!is_null($constructor)){
                //获取构造器中的方法
                $constructorParams = $constructor->getParameters();
                // var_dump($constructorParams);
                //保存构造器的参数
                foreach($constructorParams as $constructorParam){
                    //这个地方主要是判断参数是否是类,如果是就递归的构造它,不是就简单的添加到$this->params中
                    if(!is_null($constructorParam->getType())){
                        $params[] =$this->make($constructorParam->name,$constructorParam->name);
                    }else{
                        $params[] = $constructorParam->name;
                    }
                }
            }
            //在这个地方构造实例
            $class = $reflectClass->newInstanceArgs($params);
            //绑定
            $this->binds[$name] = $class;
            return $class;
        }catch(ReflectionException $e){
            echo $e->getMessage();
        }
    }

    private function __construct(){}
    private function __clone(){}

}
?>

下面是我的测试文件了,

<?php

require "./Container.php";

class TestFather{
    private $name = "TestFather";

    public function __construct(){
        
    }
}

class Test extends TestFather{
    private $name = "Test";
    // public function __construct(DI $di, DI2 $di2,$name){
        
    // }
    public function __construct(DI $di,$name,$param_2 =[]){
    }

    public function sayName(){
        echo $this->name;
    }

    public function sayDI2Name(DI2 $di2){
        //如果这么写的,di2方法会先于前面的字符串打印出来
        // echo "form Test say di2 name: ".$di2->sayName();
        echo "form Test say di2 name: ";
        echo $di2->sayName();
    }
}

class DI{
    private $name = "DI";
    public function __construct(DI2 $di2){}
    public function sayName(){
        echo $this->name;
    }    
}

class DI2{
    private $name = "DI2";
    public function __construct(){}
    
    public function sayName(){
        echo $this->name;
    }   
}

class DI3{
    private $name = "DI3";
    public function __construct(){}
    
    public function sayName(){
        echo $this->name;
    }   
}

class DI4{
    private $name = "DI4";
    public function __construct(){}
    
    public function sayName(){
        echo $this->name;
    }   
}

//要不要无所谓了
// Container::bind('test','Test'); 
$test = Container::get('test');
$test->sayName();
echo "\n";
$test->sayDI2Name(new DI2());
echo "\n";

$di = Container::get('di');
$di->sayName();

echo "\n";
$di2 = Container::get('di2');
$di2->sayName();

echo "\n";
$di3 = new DI3();
Container::get('di3',$di3)->sayName();
echo "\n";
$di4 = function(){
    return new DI4();
};

Container::get('di4',$di4)->sayName();
echo "\n";


?>

最后的结果如下
图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 .NET 6 中,WebApplication 创建主机后,会默认创建以下 DI 容器: 1. 应用程序主机容器(Host Container):用于存储应用程序的全局服务。例如,ILogger、IConfiguration、IWebHostEnvironment 等。 2. Web 主机容器(Web Host Container):用于存储 Web 应用程序特定的服务。例如,IMvcBuilder、IEndpointRouteBuilder、IApplicationBuilder 等。 3. Web 请求容器(Web Request Container):用于每个 HTTP 请求创建一个独立的容器,存储请求特定的服务。例如,HttpContext、HttpRequest、HttpResponse 等。 这些 DI 容器是通过 ASP.NET Core 中的内置 DI 容器实现的。可以使用以下方法获取 DI 容器: 1. 应用程序主机容器 ```csharp var host = WebApplication.CreateHostBuilder(args).Build(); var serviceProvider = host.Services; ``` 2. Web 主机容器 ```csharp var host = WebApplication.CreateHostBuilder(args).Build(); var webHost = host.Services.GetRequiredService<IWebHost>(); var serviceProvider = webHost.Services; ``` 3. Web 请求容器 ```csharp app.Use(async (context, next) => { var requestServices = context.RequestServices; // ... await next(); }); ``` 在以上示例中,可以通过 `GetRequiredService` 或 `RequestServices` 属性来获取 DI 容器。需要注意的是,Web 请求容器只能在请求管道中访问,不能在应用程序或 Web 主机容器中访问。 ASP.NET Core 的内置 DI 容器功能非常强大,可以用于注册和解析各种类型的服务。通过使用 DI 容器,可以轻松地将应用程序的各个部分解耦,并使应用程序更易于测试和维护。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值