c# - 使用也需要实例化的私有(private)对象实例化类的最佳方法

标签 c# solid-principles

我有一个要实例化的类 MyClass,它包含一个私有(private)属性 ObjectRepository,我想在 MyClass 的构造函数时实例化它> 被调用。

public MyClass
{
    private ObjectRepository _objectRepository;

    public MyClass()
    {

    }
}

MyClass 被实例化以添加到列表中:

objects.Add(new MyClass());

遵循 SOLID 原则最干净的方法是什么?

----编辑----

我还忘记提及的是,当我为 MyClass 编写单元测试时,我希望能够模拟 ObjectRepository。当 ObjectRepositoryMyClass 的构造函数实例化时,这是不可能的,因为在测试中没有对 _objectRepository 的引用可用。

最佳答案

为此,您需要查看 SOLID 中的 D:依赖倒置

MyClass 需要一个 ObjectRepository 的实例来完成它所做的一切;它对 ObjectRepository 具有依赖性。根据依赖倒置原则,它应该依赖于抽象,而不是具体类型。在 C# 中,执行此操作的通常方法是使用接口(interface),例如 IObjectRepository,其中包含 MyClass 需要的所有方法,但除此之外别无其他。也可以使用抽象基类来完成,但这不太常见。

当然,如果你依赖于一个接口(interface),你不知道实现它的具体类型,所以你不能实例化它。这可以;您只需要提供一个实例即可。

public MyClass
{
    private IObjectRepository _objectRepository;

    public MyClass(IObjectRepository objectRepository)
    {
        _objectRepository = objectRepository;
    }
}

现在,当您创建 MyClass 的实例时,您必须为其提供实现 IObjectRepository 的东西。

objects.Add(new MyClass(new ObjectRepository()));

在很多情况下,这就足够了。但是,对于大型对象图,像这样手动创建所有内容可能既费力又重复。解决这个问题的通常方法是使用像 IoC 容器这样的依赖注入(inject)服务。 IoC 代表控制反转,因为你正在反转事物的创造。 IoC 容器不是实例化顶部的东西并让每个东西创建它需要的东西,而是从底部开始,创建需要的东西,然后使用它来创建依赖它的东西,等等。您可以如何使用它的示例如下:

var container = new SomeIoCContainer();
container.For<IObjectRepository>().Use<ObjectRepository>();

var myClass = container.Resolve<MyClass>();

(示例语法;这在不同的 IoC 容器之间有所不同,但它们通常是这样的。)

在许多情况下,您会发现 IoC 容器可以集成到您的应用程序中,这意味着您甚至不需要显式调用容器来解决问题。例如,ASP.NET 就是为此而构建的,因此一旦配置了容器,您只需将构造函数参数添加到 Controller ,框架就会使用容器为您提供这些参数。

这种方法的优点:

  • 如果你想测试 MyClass 中发生的事情,你可以简单地给它一个假的 IObjectRepository 版本,它不会做任何复杂的事情,这样你可以用更少的工作设置您的测试,并且您知道您在 MyClass 上的测试不会受到 ObjectRepository 中可能发生的不相关事情的影响。您可以通过为测试设置一个单独的容器来完成此操作,但通常手动执行此操作更容易 - 您只测试一件事,而您的模拟依赖项不应该依赖于任何东西。
  • 随着您的应用程序的增长和变得越来越复杂,您不必担心如何创建事物所依赖的所有组件 - 您只需告诉您的 IoC 容器它们是什么,它就会负责创建事物。
  • 如果您需要更改其中一个依赖项的工作方式,那就容易多了。例如,如果您有一个从 SQL 数据库获取对象的 DatabaseObjectRepository,并且您想要将其替换为一个从 Web 服务获取对象的 WebClientObjectRepository,您只需实现相同的接口(interface)并更改您告诉容器将什么用于 IObjectRepository 的那一行,它就会为您交换应用程序中的所有用法。

关于c# - 使用也需要实例化的私有(private)对象实例化类的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56126111/

相关文章:

solid-principles - Liskov 替换原理示例

c# - IClass 不包含 method_name 的定义,也没有扩展方法 method_name

oop - 什么是依赖倒置原则,为什么它很重要?

javascript - 在按钮上点击调用一个js文件并解析它

c# - 当鼠标悬停在图像上时显示带有 linkbutton 的 div

c# - 如何从另一个窗体调用函数

c# - 在WCF数据服务中获取请求的应用程序名称

.net - .NET 的 SOLID DDD ORM 请求(使用干净的实体和存储库)

c# - 当 SRP 违规似乎将复杂性向下传递时的正确方法

c# - 建立一个简单的 websocket 握手