Blazor University (52)依赖注入 —— 拥有多个依赖项:正确的方式

本文档介绍了在Blazor组件中如何正确管理多个私有依赖项。通过从非泛型`OwningComponentBase`派生,组件可以创建自己的依赖容器,并在需要时解析所需依赖项的实例。文章详细展示了如何创建接口和实现类,如何注册这些类,以及如何在组件的`OnInitialized`方法中解析依赖项。此外,还解释了依赖项的生命周期管理,当组件被销毁时,其依赖项也会被正确释放。
摘要由CSDN通过智能技术生成

原文链接:https://blazor-university.com/dependency-injection/component-scoped-dependencies/owning-multiple-dependencies-the-right-way/

拥有多个依赖项:正确的方式

在上一节[1]中,我们看到了将多个拥有的依赖项注入组件的错误方法。本节将演示解决问题的正确方法。

如前所述,OwningComponentBase<T> 类组件将创建自己的依赖容器并在该容器中解析 T 的实例,因此 T 的实例对于我们的组件是私有的。

如果我们需要我们的组件私有地拥有多种依赖类型的实例,那么我们必须做更多的工作。为此,我们需要使用非泛型 OwningComponentBase 类。与通用版本一样,此组件将创建自己的依赖容器,该容器将在组件的生命周期内存在。但是,它不会为我们实际解析任何依赖项,而是让我们访问其依赖项容器,以便我们可以解析我们需要的任何类型的实例。

示例

源代码[2]

首先,创建一个新的 Blazor 应用程序。然后,就像我们之前所做的那样,我们将创建一些可以注入的类,这些类将使用状态成员来跟踪已创建的类实例的数量。

创建以下接口

public interface IOwnedDependency1
{
  public int InstanceNumber { get; }
}

public interface IOwnedDependency2
{
  public int InstanceNumber { get; }
}

然后创建实现这些接口的类。我将只显示第一类的代码,第二类将是相同的。

public class OwnedDependency1 : IOwnedDependency1
{
  private static volatile int PreviousInstanceNumber;

  public int InstanceNumber { get; }
  public OwnedDependency1()
  {
    InstanceNumber =
      System.Threading.Interlocked.Increment(ref PreviousInstanceNumber);
  }
}

将接口 + 它们的实现类注册为 Scoped(如果需要提醒您,请参阅比较依赖范围[3])。

接下来,编辑 Index.razor 页面,以便我们应用程序的用户可以通过单击复选框来切换组件。

@page "/"

<input id="show-component" type=checkbox @bind=ShowComponent />
<label for="show-component">Show component</label>

@if (ShowComponent)
{
  <MyOwningComponent />
}

@code
{
  bool ShowComponent = false;
}

ShowComponenttrue 时,我们的标记将创建 MyOwningComponent 的一个实例并渲染它。接下来,我们将创建 MyOwningComponent

OwningComponentBase

Shared 文件夹中,创建一个名为 MyOwningComponent 的新 Razor 组件。我们将从 OwningComponentBase 中派生此组件。

@inherits OwningComponentBase

然后创建一些类字段来保存依赖项。

@code
{
  private IOwnedDependency1 OwnedDependency1;
  private IOwnedDependency2 OwnedDependency2;
}

解决拥有的依赖关系

OwningComponentBase 创建的私有依赖性容器通过其ScopedServices 属性提供给我们。

protected IServiceProvider ScopedServices { get; }

我们可以使用这个 IServiceProvider 来解析组件所拥有的私有依赖容器中的依赖实例。

@inherits OwningComponentBase
@using Microsoft.Extensions.DependencyInjection


<div>
  OwnedDependency1.InstanceNumber = @OwnedDependency1.InstanceNumber
</div>
<div>
  OwnedDependency2.InstanceNumber = @OwnedDependency2.InstanceNumber
</div>

@code
{
  private IOwnedDependency1 OwnedDependency1;
  private IOwnedDependency2 OwnedDependency2;

  protected override void OnInitialized()
  {
    OwnedDependency1 =
      ScopedServices.GetService<IOwnedDependency1>();
    OwnedDependency2 =
      ScopedServices.GetService<IOwnedDependency2>();
  }
}
  • 第 1 行

    OwningComponentBase 继承来给我们自己的私有依赖容器。

  • 第 2 行

    使用 DependencyInjection 命名空间,因此我们可以在 IServiceProvider 上使用 GetService<T> 扩展方法。

  • 第 19 & 21 行

    使用 OwningComponentBase.ScopedServices 属性来解析组件所需的依赖项实例。

  • 第 6 & 9 行

    显示为我们创建的依赖项的实例号。

运行示例

如果我们运行示例应用并勾选复选框,我们将看到以下输出。

  • OwnedDependency1.InstanceNumber = 1

  • OwnedDependency2.InstanceNumber = 1

取消勾选该复选框以允许删除我们的组件,然后再次勾选该复选框以让 Blazor 创建 MyOwningComponent 的新实例。渲染输出现在应该如下所示。

  • OwnedDependency1.InstanceNumber = 2

  • OwnedDependency2.InstanceNumber = 2

这表明,每次创建组件时,我们在组件的 OnInitialized 方法中解析的两个依赖项都是新的实例。

依赖生命周期

OwningComponentBase 类实现 IDisposable 接口。当从OwningComponentBase 派生的任何组件不再呈现时,Blazor 将在 OwningComponentBase 上执行 Dispose 方法。

组件上的 Dispose 方法将对其拥有的私有依赖项容器调用Dispose。反过来,该容器创建的任何实现 IDisposable 的对象实例也将执行其 Dispose 方法。

要演示这种行为,请对应用程序进行以下更改。

首先,在我们的组件上重写 Dispose(bool isDisposing),并让它在被释放时输出日志。

public void Dispose()
{
  System.Diagnostics.Debug.WriteLine("Disposing " + GetType().Name);
}

然后,对于我们的每个依赖类(OwnedDependency1OwnedDependency2),让它们实现 IDisposable,并且再次让它们在执行 Dispose 时输出日志。

public class OwnedDependency1 : IOwnedDependency1, IDisposable
  {
    ... Other code omitted for brevity ...

    public void Dispose()
    {
      System.Diagnostics.Debug.WriteLine($"Created {GetType().Name} instance {InstanceNumber}");
    }
  }

我们还可以在类的构造函数中添加一些日志记录。

现在运行应用程序并切换复选框将输出类似于以下内容的日志文本。

  • Created MyOwningComponent

  • Created OwnedDependency1 instance 1

  • Created OwnedDependency2 instance 1

  • Disposing OwnedDependency2 instance 1

  • Disposing OwnedDependency1 instance 1

  • Disposing MyOwningComponent

  • Created MyOwningComponent

  • Created OwnedDependency1 instance 2

  • Created OwnedDependency2 instance 2

  • Disposing OwnedDependency2 instance 2

  • isposing OwnedDependency1 instance 2

  • Disposing MyOwningComponent

结论

当您的组件只需要拥有一个依赖项时,从 OwningComponentBase<T> 派生;当您的组件需要拥有多个依赖项时,从非泛型 OwningComponentBase 派生。

尽管解析组件依赖项实例的过程是一个手动过程,但不需要处理任何创建的依赖项,因为组件的依赖项容器将在 OwningComponentBase.Dispose 时处理它们。

参考资料

[2]

源代码: https://github.com/mrpmorris/blazor-university/tree/master/src/DependencyInjection/OwningMultipleDependenciesTheRightWay

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值