当我想简单地新建一个元素或使用 XAML 创建它时,它们是否可以克服 DI 的限制(我需要构造函数参数)?

Are they ways to overcome the limitation with DI where I need constructor arguments when I wanted to simply new up an element or create it with XAML?

我正在使用:

Microsoft.Extensions.DependencyInjection 5.0.1 版 nuget 包,我正在创建一个名为 ArrowGrid 的 class 来创建一些图形元素。

我想在 C# 中这样调用 class 并且可能 XAML:

var arrowGrid = new ArrowGrid();

<ArrowGrid />

但是 ArrowGrid 需要服务:

public class ArrowGrid : BaseGrid
{
    private readonly IGraphicsService _graphicsService;
    public ArrowGrid(IGraphicsService graphicsService)
    {
        _graphicsService = graphicsService;
        var fr         = _graphicsService.GetFrameWithArrow();
        Children.Add(fr, 3, 0);
    }
}

现在我有一个问题,因为 new ArrowGrid() 会给我一个错误,说没有没有参数的默认构造函数,所以我有一个想法:

public class ArrowGrid : BaseGrid
{
    private readonly IGraphicsService _graphicsService;
    public ArrowGrid()
    {
        _graphicsService = Startup.ServiceProvider.GetRequiredService<GraphicsService>();
        var fr         = _graphicsService.GetFrameWithArrow();
        Children.Add(fr, 3, 0);
    }
}

但是从我读到的内容来看,总是建议使用构造函数参数:

Of course, you typically shouldn't be using the IServiceProvider directly in your code at all. Instead, you should be using standard constructor injection, and letting the framework worry about using IServiceProvider behind the scenes.

只是 Microsoft.Extensions.DependencyInjection 有问题吗?其他 DI 解决方案怎么样?我不知道这些,如果他们提供更多功能,我将不胜感激。我的想法也是克服这个问题的正确方法吗?请注意,在这种情况下,graphicsService 是一项非常简单的服务,我在进行测试时永远不需要替换它。

这是我目前正在做的事情:

var abc = new ArrowGrid
{
   Text1               = "Talk to us",
   TapCommandParam     = "Home/FBPage",
   IconSource          = Const.IconSource.CardOptions,
};

这里我认为是建议:

var abc = Startup.ServiceProvider.GetRequiredService<ArrowGrid>();
abc.Text1 = "Talk to us";
abc.TapCommandParam = "Home/FBPage";
abc.IconSource = Const.IconSource.CardOptions;

Startup.ServiceProvider.GetRequiredService<ArrowGrid>() 对我来说看起来不错,但有更好的方法来做到这一点。 DI Container 允许您变得懒惰,而不是使用 new 或强制性地使用 DI Container 自己创建任何东西。

考虑这个例子。希望你编写代码的 class 注册在 ServiceCollection.

public class MyTestClass
{
    public MyTestClass()
    {
        var abc = Startup.ServiceProvider.GetRequiredService<ArrowGrid>();
        abc.Text1 = "Talk to us";
        abc.TapCommandParam = "Home/FBPage";
        abc.IconSource = Const.IconSource.CardOptions;
    }
}

可以轻松替换为相同的 DI 版本。

public class MyTestClass
{
    public MyTestClass(ArrowGrid abc)
    {
        abc.Text1 = "Talk to us";
        abc.TapCommandParam = "Home/FBPage";
        abc.IconSource = Const.IconSource.CardOptions;
    }
}

这就是注册 classes 的应用程序组合根的意义。