I was refactoring a quite large WPF project and I found some pieces of code where it can leads to error.
Ive got some services in the form
public sealed class CurrenciesService : ContainerServiceBase<Currency>, ICurrenciesService
{
public override Currency GetItem(int id)
{
return GetItemInternal(x => x.Id == id);
}
public override Task Init()
{
return PerformInitInternal(InitCacheMessages.STR_GET_COUNTERPARTS,
InitCacheMessages.STR_GET_COUNTERPARTS_FAILED,()=> CommonRepository.GetCurrenciesAsync());
}
}
where the ContainerServiceBase is something as
public class ContainerServiceBase<T> : IContainerBase<T>
where T : class
{
#region Variables
protected readonly IExceptionService ExceptionService = ServiceLocator.Default.ResolveType<IExceptionService>();
protected readonly ICommonRepository CommonRepository = ServiceLocator.Default.ResolveType<ICommonRepository>();
public delegate void ItemsChangedHandler(object sender, EventArgs e);
public event ItemsChangedHandler OnItemsChanged;
#endregion
public virtual T GetItem(int id)
{
throw new NotImplementedException();
}
public virtual Task Init()
{
return TaskEx.WhenAll();
}
public IList<T> Items { get; protected set; }
protected async Task PerformInitInternal(string okMessage, string koMessage, Func<Task<IList<T>>> function)
{
try
{
var result = await function();
if (result != null)
{
Items = result;
LogTo.Information(okMessage, result.Count);
OnItemsChanged?.Invoke(this, new EventArgs());
}
else
{
LogTo.Warning(koMessage);
}
}
catch (Exception ex)
{
ExceptionService.HandleException(ex);
}
}
protected T GetItemInternal(Func<T, bool> condition)
{
if (Items == null) throw new NullReferenceException("Items has not been initialized");
var result = Items.FirstOrDefault(condition);
return result;
}
Currently during the Application's start I perform for each service this
var taskPortolio = portfoliosService.Init();
var taskInstitutes = institutesService.Init();
var taskStatus = statusService.Init();
var taskCounterparts = counterpartsService.Init();
var taskCrosses = crossesService.Init();
var taskCurrencies = currenciesService.Init();
var taskSigns = signsService.Init();
var taskCrossSplit = crossSplitService.Init();
var taskDateMM = dateMmService.Init();
var taskSignsFx = signsFxService.Init();
var taskPortfolioTree = portfolioItemService.Init();
var taskTags = tagService.Init();
var taskInstitutesCustomerDesk = institutesCustomerDeskService.Init();
var taskProvenances = provenanceService.Init();
var taskRepoClasses = repoClassService.Init();
var taskDatesMaturity = dateMaturityService.Init();
Those methods are initialized even if they're never used.
I was writing a unit test in the form
[Test]
public async Task CurrenciesLoaded()
{
var viewmodel = viewModelFactory.CreateViewModel<HistoricalDetailPRTViewModel>(null, null);
var res = viewmodel.InitializeViewModelAsync();
await res;
Assert.NotNull(viewmodel.Currencies);
Assert.IsTrue(viewmodel.Currencies.Count>0);
}
and correctly I get null at viewmodel.Currencies since no CurrenciesService.Init has been called.
Can I put a check in the Item.getter to check if it's called the Init and if not call it? is this evil? consider that those init are now called async and I wish not to block the UI while it's loading
P.S. I'm using Catel as MVVM Framework