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

Posted

技术标签:

【中文标题】blazor wasm 如何从 di 注入自定义类【英文标题】:blazor wasm how to inject from di into custom class 【发布时间】:2021-04-30 06:29:34 【问题描述】:

有没有办法将 httpClient 注入到我自己的自定义类中?

明确一点 - 我知道如何在 blazor 中使用 DI 注入组件或其他服务。 只是为了测试它的可能性。

我想做一些类似代码的事情

protected override async Task OnInitializedAsync()

  GSP gsp = new GSP("db1","table1");
  gsp.get("users", ()=> do something with data); // and this should call api and get users

所以我有

public class GSP

    [Inject]
    public HttpClient httpClient  get; set; 
 ...

但它是null

我还检查了 ctor 选项

    public GSP(HttpClient httpClient)
    
        this.httpClient = httpClient;
    

但是我必须手动传递这个注入到组件中的 httpClient。

我可以的

  private HttpClient httpClient = new HttpClient  BaseAddress 

但是我没有 BaseAdres。听说我们又去了 - 在这个地方得到这个 BaseAddres 的更简单的方法? ;)

有可能吗?或者这只是“糟糕的做法”,这就是我找不到的原因? 非常感谢!

【问题讨论】:

重复? ***.com/questions/65629065/… 关闭但没有,因为我想自己创建对象并将 DI 注入作为该类的属性 【参考方案1】:

通过 ctor 和 HttpClientFactory,您可以执行以下操作:

public class Program

    public static async Task Main(string[] args)
    
         var builder = WebAssemblyHostBuilder.CreateDefault(args);
         builder.Services
         .AddTransient<GSP>()
         .AddHttpClient().ConfigureHttpClient(httpClient =>
         
              httpClient.BaseAddress = builder.HostEnvironment.BaseAddress;
         );
         await host.RunAsync();
    

或者没有 HttpClientFactory

public class Program

    public static async Task Main(string[] args)
    
         var builder = WebAssemblyHostBuilder.CreateDefault(args);
         builder.Services
         .AddTransient(p => new GSP(new HttpClient  BaseAddress = builder.HostEnvironment.BaseAddress );

         await host.RunAsync();
    

【讨论】:

【参考方案2】:

我觉得this article里的解释还不错:

复杂的服务可能需要额外的服务。在下面的 例如,DataAccess 需要 HttpClient 默认服务。 @注入 (或 [Inject] 属性)不可用于服务。 必须改用构造函数注入。所需的服务是 通过向服务的构造函数添加参数来添加。

你在正确的轨道上:

 public GSP(HttpClient httpClient)
    
        this.httpClient = httpClient;
    

但这是你误会的地方

但是我必须手动传递这个注入的 httpClient 以组件为例。

不要手动传递任何东西。而是将您的 GSP 类注入到您的组件中。

在您的剃须刀组件基类中:

   [Inject]
    public GSP myGspService  get; set; 

或直接在剃刀文件中:

@Inject GSP myGspService

如果您每次使用时都想要一个新实例,请注入一个GSPFactory 类。您不能直接使用 DI 注入未注册的参数(例如您的“db1”和“table1”),工厂类必须处理它,或者您必须在每次创建时设置它们..

在您的剃须刀组件基类中:

   [Inject]
    public GSPFactory myGspService  get; set; 

或直接在剃刀文件中:

@Inject GSPFactory myGspService

和你的工厂类:

public class GSPFactory 
   Func<GSP> iocFactory;
   public GSPFactory(Func<GSP> iocFactory) 
      this.iocFactory = iocFactory;
   

   public GSP Create(string option1, string option2) 
      var gsp = this.iocFactory();
      gsp.Option1 = option1;
      gsp.Option2 = option2;
      return gsp;
   

设置可能如下所示:

Services.AddTransient<GSP>()
.AddTransient<Func<GSP>>(x => () => x.GetService<GSP>())
.AddSingleton<GSPFactory>() // (... plus httpClient etc)

如果你坚持要注入属性,工厂类变体:

public class GSPFactory 
   HttpClient httpClient;
   public GSPFactory(HttpClient httpClient) 
      this.httpClient= httpClient;
   

   public GSP Create(string option1, string option2) 
      var gsp = new GSP(option1, option2);
      gsp.HttpClient= httpClient;
      return gsp;
   

然后设置可能看起来像这样:

Services.AddSingleton<GSPFactory>() // (... plus httpClient etc)

在任何情况下,您总是会注入工厂,并像这样获取 GSP 的新实例:

injectedGspFactory.Create("db1", "table1");

【讨论】:

thx 我更新了我的 quastion,因为我稍微简化了它,我现在看到这也很重要 - 如果我想使用自己的 ctor,比如 new GSP("db1","table1"); ?也有可能吗?或者这是限制 - 我可以像你发布的那样 DI 这个 GSP 但不能使用自己的 ctors?

以上是关于blazor wasm 如何从 di 注入自定义类的主要内容,如果未能解决你的问题,请参考以下文章

Blazor 应用程序作为 WASM 或服务器运行。无法让依赖注入在服务器模式下工作

在自定义类中访问 Blazor 服务器端的 AuthenticationStateProvider

Blazor WASM - 流畅的验证

在 blazor 中使用自定义组件时在注入的差异服务中调用 HttpContextAccesor 后为 null

Blazor Wasm 独立发布到 IIS

C#:如何在 Blazor Wasm 托管中将动态 Razor 组件从服务器发送到客户端?