gpt4 book ai didi

c# - 通用与依赖注入(inject)

转载 作者:太空狗 更新时间:2023-10-29 19:39:37 25 4
gpt4 key购买 nike

Generic Classes 和 Dependency injection 之间有什么区别吗? 他们不是实现控制反转的方法吗

泛型类不是一种实现依赖注入(inject)并增加编译时安全性的方法吗?

例如,如果我有一个节点类,那么我可以定义如下

class Node<T> where T : ISomeInterface
{
..
..
}

class Node
{
ISomeInterface obj
public Node(ISomeInterface inject)
{
obj = inject;
}
}

更新 2随着新

class Node<T> where T : ISomeInterface, new()
{
ISomeInterface obj
public Node()
{
obj = new T();
}
}

更新 3@akim:我已经制作了您要求使用泛型的示例使用泛型的存储库

Interface IRepository 
{
public DataTable GetAll();
}

public class ProductRep : IRepository
{
public DataTable GetAll()
{
//implementation
}
}

public class MockProductRep : IRepository
{
public DataTable GetAll()
{
//mock implementation
}
}

public class Product<T> where T : IRepository, new()
{
IRepository repository = null
public Product()
{
repository = new T();
}
public List<Product> GetProduct()
{
DataTable prodlst = repository.GetAll();
//convert to List of products now
}
}


//so while using the Product class, client would Supply ProductRep class and in NUnit you //would supply MockProductRep class

Product<ProductRep> obj = new ProductRep<ProductRep>();
List<Product> lst = obj.GetProduct();

//in NUnit
Product<MockProductRep> obj = new ProductRep<MockProductRep>();
List<Product> lst = obj.GetProduct();

最佳答案

它们不一样。通用类型允许您定义可应用于范围广泛的其他类型的功能。但是,当您实例化泛型类时,编译器会引用作为泛型参数传递的实际类型。所以声明是静态的,编译后不能改变。例如,我可以编写实例化您的 Node 类的代码:

Node<SomeImplementation> node1 = new Node<SomeImplementation>();
Node<SomeOtherImplementation> node2 = new Node<SomeOtherImplementation>();

我在不同的场景中重用了您的 Node 类,但是一旦我编译了我的程序集,我就无法更改我的变量(node1 和 node2)的泛型类型。

另一方面,依赖注入(inject)(和 IoC 容器)允许您在运行时更改应用的功能。您可以使用依赖注入(inject)在运行时用完全不同的实现替换 ISomeInterface 的一个实现。例如,在您的第二个节点类中,我可以使用 IoC 容器来创建 Node 类...类似于:

Node n = Container.Create<Node>();

然后 IoC 容器会根据一些配置确定如何实例化 Node 类。它确定构造函数需要 ISomeInterface 的实现,并且它知道如何在运行时 构建实现。我可以更改 IoC 容器的配置并执行相同的程序集/代码,然后将创建 ISomeInterface 的不同实现并将其传递给 Node 的构造函数。

这在单元测试中很有用,因为您可以模拟应用程序的某些部分,以便测试一个特定的类。例如,您可能想要测试一些通常访问数据库的业务逻辑。在您的单元测试中,您可以模拟您的数据访问逻辑并注入(inject)新功能来返回测试每个特定业务案例所需的“静态”数据。这打破了您的测试对数据库的依赖,并允许进行更准确/可维护的测试。

编辑

关于您的更新,可能并不总是需要无参数构造函数限制。您可能有一个需要参数的类(由您或第三方编写)。要求类实现无参数构造函数可能会影响应用程序的完整性。 DI 模式背后的想法是您的 Node 类不需要知道该类的实际创建方式。

假设您有很多层的类/依赖项。对于通用类型,它可能看起来像这样:

class MyClass<T>
where T : IUtilityClass
{
...
}

class UtilityClass<T> : IUtilityClass
where T : IAnotherUtilityClass
{
...
}

class AnotherUtilityClass : IAnotherUtilityClass
{
...
}

在这种情况下,MyClass 使用 UtilityClass,而 UtilityClass 依赖于 AnotherUtilityClass。所以当你声明 MyClass 时,你必须知道每一个依赖项......不仅仅是 MyClass 的依赖项,还有 UtilityClass 的依赖项>。这个声明看起来像这样:

MyClass<UtilityClass<AnotherUtilityClass>> myTestClass =
new MyClass<UtilityClass<AnotherUtilityClass>>();

随着您添加越来越多的依赖项,这会变得很麻烦。使用 DI,您的调用者不需要了解任何嵌套依赖项,因为 IoC 容器会自动找出它们。你只需做这样的事情:

MyClass myTestClass = Container.Create<MyClass>();

无需了解 MyClass 或其实用类的任何细节。

IoC 容器通常还有其他好处,例如,其中许多容器提供面向方面编程的形式。它们还允许您指定一个对象的生命周期,因此一个对象可以是一个单例(只会创建一个实例,并且相同的实例将返回给所有调用者)。

关于c# - 通用与依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11715317/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com