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

blazor wasm how to inject from di into custom class

有没有办法将 httpClient 注入我自己的自定义 class?

澄清一下 - 我知道如何在 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 的更简单的方法? ;)

可能吗?或者只是 'bad practise' 这就是我找不到的原因? 非常感谢!

通过 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();
    }
}

我觉得this article里面的解释很好:

Complex services might require additional services. In the following example, DataAccess requires the HttpClient default service. @inject (or the [Inject] attribute) isn't available for use in services. Constructor injection must be used instead. Required services are added by adding parameters to the service's constructor.

你走在正确的轨道上:

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

但你错了

but then i have to pass this httpClient manualy that was injected into component for example.

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

在你的剃须刀组件库中 class:

   [Inject]
    public GSP myGspService { get; set; }

或直接在 razor 文件中:

@Inject GSP myGspService

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

在你的剃须刀组件库中 class:

   [Inject]
    public GSPFactory myGspService { get; set; }

或直接在 razor 文件中:

@Inject GSPFactory myGspService

和你的工厂class:

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)

factory class 变体如果你坚持注射 属性:

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");