У меня есть служба AppState, которая имеет следующее:
public event Action OnDataChanged;
public MyObject CurrentObject { get; private set; }
public void UpdateMyObject(MyObject obj)
{
CurrentObject = obj;
OnDataChanged?.Invoke();
}
В одном компоненте я называю UpdateMyObject
. Служба AppState
получает правильные данные, и вызывается OnDataChanged?.Invoke()
.
В другом компоненте, на который предполагается подписка OnDataChanged
для принятия решения об обновлении данных, у меня есть следующее:
protected override void OnInitialized()
{
AppStateService.OnDataChanged+= UpdateData;
}
private void UpdateData()
{
var data = AppStateService.CurrentObject;
}
Я пытался поставить точки останова по всему компоненту «прослушивание», но ничего не получилось. Есть идеи, что я делаю не так и почему не вызывается UpdateData
метод OnChanged?.Invoke
из госслужбы? Предложения о том, как отладить это?
Вот мой код, который работает — я создал его в решении шаблона Blazor Server. Я сделал ваш объект строкой для простоты.
public class AppState
{
public Guid Id { get; } = Guid.NewGuid();
public event Action? OnDataChanged;
// This is more normal for events
public event EventHandler? DataChanged;
public string? CurrentObject { get; private set; }
public void UpdateMyObject(string obj)
{
CurrentObject = obj;
OnDataChanged?.Invoke();
DataChanged?.Invoke(this, new EventArgs());
}
}
Регистрация службы
builder.Services.AddSingleton<WeatherForecastService>();
// Set as a singleton as the name suggests it's application specific and not user specific
builder.Services.AddSingleton<AppState>();
Компонент для отображения состояния
// AppStateComponent.razor
@inject AppState AppStateService
@implements IDisposable
<h3>AppStateComponent</h3>
<div class = "m-2 p-2">
Service ID: @this.AppStateService.Id.ToString()
</div>
<div>
Data: @this.data
</div>
@code {
private string data = string.Empty;
protected override void OnInitialized()
{
this.AppStateService.OnDataChanged += UpdateData;
}
private void UpdateData()
{
data = this.AppStateService.CurrentObject!;
this.InvokeAsync(StateHasChanged);
}
public void Dispose()
{
this.AppStateService.OnDataChanged -= UpdateData;
}
}
И тестовая страница
@page "/"
@inject AppState AppStateService
<div class = "m-2 p-2">
Service ID: @this.AppStateService.Id.ToString()
</div>
<AppStateComponent />
<div class = "m-2">
<button class = "btn btn-dark" @onclick=UpdateData>Update</button>
</div>
@code {
private void UpdateData()
{
this.AppStateService.UpdateMyObject($"Updated at {DateTime.Now.ToLongTimeString()}");
}
}
@enet - вот почему я добавил комментарий - // Установить как синглтон, как следует из названия, он зависит от приложения, а не от пользователя. В противном случае, как вы говорите, сделайте это Scoped
. Ждал отзывов.
@MrCakaShaunCurtis да, у меня это тоже работает в новом серверном приложении blazor, но в корпоративном приложении, над которым я работаю, тот же код не достигает точки останова в компоненте прослушивания.
Тогда вы не можете ссылаться на один и тот же экземпляр объекта. Добавьте идентификатор Guid
в свою государственную службу и убедитесь, что идентификатор совпадает с тем, что я показал в ответе. Также обратите внимание, что я добавил Dispose в ответ. Является ли ваша государственная служба одноэлементной или ограниченной службой?
AddSingleton<AppState>();
Я думаю, что это должен быть AddScoped, иначе экземпляр AppState будет использоваться всеми соединениями.