Ana*_*and 8 c# generics design-patterns dependency-injection
Generic Classes和Dependency注入之间有什么区别吗?它们不是实施控制反转的方法
泛型类不是一种实现依赖注入的方法,还有编译时安全性的附加好处吗?
例如,如果我有一个节点类,那么我可以定义如下
class Node<T> where T : ISomeInterface
{
..
..
}
class Node
{
ISomeInterface obj
public Node(ISomeInterface inject)
{
obj = inject;
}
}
Run Code Online (Sandbox Code Playgroud)
更新2 与新
class Node<T> where T : ISomeInterface, new()
{
ISomeInterface obj
public Node()
{
obj = new T();
}
}
Run Code Online (Sandbox Code Playgroud)
更新3 @akim:我做了一个例子,你要求使用Generics使用Generics Repository
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();
Run Code Online (Sandbox Code Playgroud)
他们不一样。泛型类型允许您定义可应用于各种其他类型的功能。但是,当您实例化泛型类时,编译器会引用作为泛型参数传递的实际类型。所以声明是静态的,编译后不能改变。例如,我可以编写实例化 Node 类的代码:
Node<SomeImplementation> node1 = new Node<SomeImplementation>();
Node<SomeOtherImplementation> node2 = new Node<SomeOtherImplementation>();
Run Code Online (Sandbox Code Playgroud)
我在不同的场景中重用您的 Node 类,但是一旦编译了程序集,我就无法更改变量的通用类型(node1 和 node2)。
另一方面,依赖注入(和 IoC 容器)允许您在运行时更改应用程序的功能。您可以使用依赖注入在运行时将一种实现替换ISomeInterface为一种完全不同的实现。例如,在您的第二个节点类中,我可以使用 IoC 容器来创建 Node 类...类似于:
Node n = Container.Create<Node>();
Run Code Online (Sandbox Code Playgroud)
然后,IoC 容器会根据某些配置确定如何实例化 Node 类。它确定构造函数需要 的实现ISomeInterface,并且知道如何在运行时构建实现。我可以更改 IoC 容器的配置并执行相同的程序集/代码,并且ISomeInterface将创建不同的实现并将其传递给 Node 的构造函数。
这在单元测试中很有用,因为您可以模拟应用程序的某些部分,以便可以测试一个特定的类。例如,您可能想要测试一些通常访问数据库的业务逻辑。在单元测试中,您可以模拟数据访问逻辑并注入新功能,以返回测试每个特定业务案例所需的“静态”数据。这打破了测试对数据库的依赖,并允许更准确/可维护的测试。
编辑
关于您的更新,可能并不总是需要无参数构造函数限制。您可能有一个需要参数的类(由您或第三方编写)。要求类实现无参数构造函数可能会影响应用程序的完整性。DI 模式背后的想法是,您的 Node 类不需要知道该类的实际创建方式。
假设您有许多层的类/依赖项。对于泛型类型,它可能看起来像这样:
class MyClass<T>
where T : IUtilityClass
{
...
}
class UtilityClass<T> : IUtilityClass
where T : IAnotherUtilityClass
{
...
}
class AnotherUtilityClass : IAnotherUtilityClass
{
...
}
Run Code Online (Sandbox Code Playgroud)
在本例中,MyClass 使用 UtilityClass,而 UtilityClass 又依赖于 AnotherUtilityClass。因此,当您声明 时MyClass,您必须知道每一个依赖项……不仅是 的依赖项MyClass,还包括 的依赖项UtilityClass。这个声明看起来像这样:
MyClass<UtilityClass<AnotherUtilityClass>> myTestClass =
new MyClass<UtilityClass<AnotherUtilityClass>>();
Run Code Online (Sandbox Code Playgroud)
当您添加越来越多的依赖项时,这会变得很麻烦。使用 DI,您的调用者不需要了解任何嵌套依赖项,因为 IoC 容器会自动找出它们。你只需做这样的事情:
MyClass myTestClass = Container.Create<MyClass>();
Run Code Online (Sandbox Code Playgroud)
无需了解有关 MyClass 或其实用程序类的详细信息。
IoC 容器通常还有其他好处,例如它们中的许多提供面向方面编程的形式。它们还允许您指定对象的生命周期,因此对象可以是单例(仅创建一个实例,并且将向所有调用者返回相同的实例)。
| 归档时间: |
|
| 查看次数: |
4739 次 |
| 最近记录: |