elektra
elektra

Reputation: 115

How to pass a parameter to a Blazor service?

I have a service like this sample code below:

using System.Collections.Generic;
using System.Threading.Tasks;
namespace BasicDependencyInjection
{
  public interface IToDoApi
  {
    Task<IEnumerable<ToDo>> GetToDosAsync();
  }
  public class ToDoApi : IToDoApi
  {
    private readonly IEnumerable<ToDo> Data;
    public ToDoApi()
    {
      Data = new ToDo[]
      {
        new ToDo { Id = 1, Title = "To do 1", Completed = true},
        new ToDo { Id = 2, Title = "To do 2", Completed = false},
        new ToDo { Id = 3, Title = "To do 3", Completed = false},
      };
    }
    public Task<IEnumerable<ToDo>> GetToDosAsync() => Task.FromResult(Data);
  }
}

It's not my code, just a sample code taken a tutorial page

And here is how the service is registerd.

service.AddSingeton<IToDoApi, ToDoApi>();

My question is, I need to pass a value to the service, namely to the ToDoApi() method.

How can this be done? How can I pass a token to the service for example without hardcoding it in the code.

One more thing, I can't pass a param to the register method, I would like to pass a param whenever I am using the service in my compoents, because the token to provide the service comes from components.

Thanks

Upvotes: 1

Views: 1081

Answers (1)

MrC aka Shaun Curtis
MrC aka Shaun Curtis

Reputation: 30001

You need to do something like this:

public class ToDo
{
    public int Id { get; set; }
    public string Title { get; set; } = string.Empty;
    public bool Completed { get; set; }
}

public interface IToDoApi
{
    Task<IEnumerable<ToDo>> GetToDosAsync();
}

public class ToDoApi : IToDoApi
{
    private readonly IEnumerable<ToDo> Data;

    private bool initialized;
    
    public ToDoApi()
    {
        Data = new ToDo[]
        {
        new ToDo { Id = 1, Title = "To do 1", Completed = true},
        new ToDo { Id = 2, Title = "To do 2", Completed = false},
        new ToDo { Id = 3, Title = "To do 3", Completed = false},
        };
    }
    public void Initialize(bool initialize)
    {
        initialized = initialize;
    }

    public Task<IEnumerable<ToDo>> GetToDosAsync()
    {
        if (!initialized)
            throw new Exception("You must initialize ToDoAPI before trying to use it");
        
        return Task.FromResult(Data);
    } 
}

You call Initialize from your component that gets the data and pass in whatever data you want. I've made it simplistic by just passing in the actual bool.

Service registration:

builder.Services.AddScoped<ToDoApi>();

Here's a demo page:

@page "/"
@inject ToDoApi Service

<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<div class="p-2 m-2 ">
    Records: @list.Count();
</div>

<div class="p-2 m-2 ">
    <button class="btn btn-danger" @onclick="First">Unsafe</button>
    <button class="btn btn-primary" @onclick="Second">Safe</button>
</div>
@code {
    IEnumerable<ToDo> list = Enumerable.Empty<ToDo>();

    private async Task First()
    {
        list = await Service.GetToDosAsync();
    }

    private async Task Second()
    {
        Service.Initialize(true);
        list = await Service.GetToDosAsync();
    }
}

Upvotes: 4

Related Questions