混合 Blazor 组件、DI 和 C# 8 可为空

Posted

技术标签:

【中文标题】混合 Blazor 组件、DI 和 C# 8 可为空【英文标题】:Mixing Blazor Components, DI and C# 8 nullable 【发布时间】:2021-02-23 06:54:49 【问题描述】:

我在一个启用了 nullable 的项目中将 .net 5 用于 Blazor 应用程序。它使用 Code Behind 来创建 Blazor 组件。我想使用构造函数,这样我就可以避免将每个非 DI 属性标记为可为空,以简化在我的 blazor 代码中访问它们。但是,如果我创建一个构造函数 public PageNumberOne(ILogger<PrimaryItem> logger)

我收到错误 MissingMethodException: No parameterless constructor defined for type

如果我在 DI 项上使用注入属性,那么我会收到警告 - 非空属性 _logger 在激发构造函数时必须包含非空值

那么如何在不将每个属性都标记为可为空的情况下将 DI 与可为空的混合使用?

我也可以在“代码”块的主体中​​创建它们,但是我无法访问我的 DI 项进行初始化,因为它们在 OnInitialized 之前不可用。所以我必须再次将它们标记为 Nullable。

【问题讨论】:

如果您使用 .razor.cs 代码隐藏文件,您可以使构造函数注入工作。请参阅此处提供的解决方案:github.com/dotnet/aspnetcore/issues/… 【参考方案1】:

我在相同的场景中工作:Blazor 组件 + Nullable。我所做的是将参数声明为可为空,并在使用参数时使用! (null-forgiving) operator:

[Inject]
public NavigationManager? MyNavigationManager get; set;

[Parameter]
public MenuItem? MyMenuItem get; set;

protected void Foo()

    var currenturi = MyNavigationManager!.Uri; //<--- here
    var sometext = MyMenuItem!.text; //<--- here
    // ...

Kirk Woll 通过评论的替代方案,在我看来更优雅:

或者,假设注入将起作用并声明如下属性:

[Inject]
public NavigationManager MyNavigationManager get; set; = default!;

我已经对其进行了测试,并且可以在没有无参数构造函数的接口或类中正常工作。

【讨论】:

或者,假设注入将起作用并声明属性如public NavigationManager MyNavigationManager get; set; = default!; @KirkWoll,真的吗?我一定要试试!!!看起来是一个更好的解决方案! @KirkWoll,我刚刚测试了它通过[Inject] private IWeatherForecastService ForecastService get; set; = default!; 之类的接口注入,它运行起来就像一个魅力。 WTF,如何将接口实例化为default!?您是否愿意发表您的评论作为删除我的评论并投票支持您的方法的答案?问候。 您的回答很好,感谢您的信任。 :) 但解释很简单。对于接口或类,default 就是null! 运算符在运行时不做任何事情,它只是向编译器保证它实际上不会为空。要记住的重要一点是,最近引入的所有可空性都是由编译器处理的,而不是运行时。 @KirkWoll: twitter.com/ctrl_alt_d/status/1364521983225065475?s=20 :)

以上是关于混合 Blazor 组件、DI 和 C# 8 可为空的主要内容,如果未能解决你的问题,请参考以下文章

有啥方法可以通过“http 请求”和通过 DI 在 Blazor 组件中的“DI 范围”中为每个用户提供持久性?

Blazor 服务器:将 EF Core DbContextFactory 与 DbContext 混合

深入浅出Blazor webassembly之razor组件的C#代码组织形式

blazor wasm 如何从 di 注入自定义类

基于C#和Blazor开发的前后端分离框架

如何在 Blazor 中编写自定义值更改事件处理程序?