Reputation: 115
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
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