我正在寻找一个更大的依赖注入示例以及如何实现它。如果类A依赖于类B并将类C的引用传递给B的构造函数,那么类A是否也必须在它的构造函数中引用类C?这意味着应用程序中的main方法应该真正创建所有类,听起来很奇怪?
据我所知,使用DI框架我们可以在某种程度上将它放在XML文件中,但听起来很难快速查看真正实例化的类型?特别是如果它是一个非常大的应用程序。
答案 0 :(得分:2)
你是对的,每个DI框架都有不同的管理方式。
一些使用属性等属性来表示依赖,然后“自动”提供正确类型的实例,而其他(比如.net的城堡windsor)允许xml配置,流畅或其他方法“连接”依赖图。
同样不,A类对使用C实例构建的B实例进行构建引用。除非通过B公开,否则无需知道C语言。
public class C { }
public class B { public B(C c) { ... }}
public class A { public A(B b) { ... }}
// manual wireup
C c = new C();
B b = new B(c);
A a = new A(b);
// DI framework
InversionOfControlContainer container = new InversionOfControlContainer(... some configuration);
A a = container.ResolveInstanceOf<A>();
// container dynamically resolves the dependencies of A.
// it doesnt matter if the dependency chain on A is 100 classes long or 3.
// you need an instance of A and it will give you one.
希望有所帮助。
答案 1 :(得分:1)
你没说过你用的语言。下面我的例子是使用Unity容器的C#。 (显然通常你会使用接口而不是具体的类型):
container = new UnityContainer();
container.RegisterType<C>();
container.RegisterType<B>();
A a = container.Resolve<A>();
答案 2 :(得分:1)
这里有一些PHP语言的例子,希望这有助于你理解
class Users
{
var $Database;
public function __construct(Database $DB)
{
$this->Database = $DB;
}
}
$Database = Database::getInstance();
$Users = new Users($Database);
在此示例中,new
关键字用于方法getInstance()
,您也可以
$Users = new Users(Database::getInstance());
或者解决这个问题的另一种方法是
class Users
{
/*Dependencies*/
private $database,$fileWriter;
public function addDependency($Name,$Object)
{
$this->$Name = $Object;
return $this;
}
}
$Users = new Users();
$Users->addDependency('database',new Database)->addDependency('fileWriter',new FileWriter);
更新
老实说,我从不使用依赖注入,因为它所做的就是将对象传递给类来创建局部范围。
我倾向于创建一个全局实体,并在其中存储对象,因此只存储在1个变量中。
让我向您展示一个小例子:
abstract class Registry
{
static $objects = array();
public function get($name)
{
return isset(self::$objects[$name]) ? self::$objects[$name] : null;
}
public function set($name,$object)
{
self::$objects[$name] = $object;
}
}
好的,这类课程的美妙之处在于
当您的系统加载并且包含并初始化所有对象时,您可以将它们存储在这里,如下所示:
Registry::add('Database',new Database());
Registry::add('Reporter',new Reporter());
只要你在运行时,就可以像使用全局变量一样使用它:
class Users
{
public function getUserById($id)
{
$query = "SELECT * FROM users WHERE user_id = :id";
$resource = Registry::get("Database")->prepare($query);
$resource->bindParam(':id',$id,PDO::PARAM_INT);
if($resource->execute())
{
//etc
}else
{
Registry::get('Reporter')->Add("Unable to select getUserById");
}
}
}
我看到这种对象传递方式更加清晰
答案 3 :(得分:0)
如果有人还在寻找一个很好的例子,它显示没有IoC容器的DI(穷人的DI)以及IoC容器(本例中为Unity)并在代码中注册类型,也可以用XML注册,你可以查看: https://dannyvanderkraan.wordpress.com/2015/06/15/real-world-example-of-dependeny-injection/