Base description and context:
Structure-wise there is a database object that has lists of objects (basically each list is a table), and each member of said lists can have its own lists.
All the XML stuff gets done in the background so the coder doesn't have to worry about that.
If an object in a list has a list or lists of his own, they are empty until object.open()
is called (loading data from XML to memory).
The problem is navigating this structure. It would be great if I could call something like GetLazilyInitializedXX()
that would return a new list with the same references, but which has an automated action when any member is accessed (but ONLY then. Not all of them, unless foreach really goes through all of them for example!). Something like LazyList<>
.
Example of use: I need to find the latest yCount
(called amount
in the code) data from a deeper part of the structure. The lists are sorted from the oldest record date to newest. So currently I have to make a new list with a reversed order, use foreach on each subsequent list and manually call .open()
on the list members, and return the selection when yCount
is reached.
If the objects in lists would have .open()
when being accessed / getted (on any way, i.e. even in foreach and only those that really were "getted") from such a "LazyList", a "select / where" could be used (even in foreach), simplifying a lot of the code and removing a lot of the nesting.
Current WIP code (with a substantial amount of nesting):
/// <summary>
/// Gets the latest Daily Test Data.
/// </summary>
/// <param name="amount">The amount of Daily Tests to get</param>
/// <param name="fromDateTime">The date to get Daily Tests from (default - today)</param>
/// <returns></returns>
public static List<QCUnitDailyTestData> GetLatestDailyTestData(int amount = 1, DateTime? fromDateTime = null)
{
List<QCUnitDailyTestData> result = new List<QCUnitDailyTestData>();
//Removing the time from the date. If fromDateTime is null, using current DateTime
var fromDate = fromDateTime?.Date ?? DateTime.Now.Date;
Log.Info("Selecting " + amount + " latest Daily Tests from: " + fromDate); //todo format fromDate?
//We need to go through years from the latest to oldest.
foreach (ProductionYear productionYear in Database.GetProductionYearsFromLatest())
{
//LazyInit!
productionYear.Open();
//We need to go through days from the latest to oldest.
foreach (ProductionDay productionDay in productionYear.GetProductionDaysFromLatest())
{
//LazyInit!
productionDay.Open();
//If the production day is before fromDate or it is the same day as fromDate...
if (productionDay.Data.Date.Date.CompareTo(fromDate) < 1)
{
//We only want the newest daily test. The other ones (in the same day) aren't used!
QCUnitDailyTest dailyTest = productionDay.GetDailyTestsFromLatest().FirstOrDefault();
//A day doesn't have to have a daily test - if there is no daily test, continue with the next day
if (dailyTest == null) continue;
//LazyInit!
dailyTest.Open();
result.Add(dailyTest.Data); //Adding to the resulting list
//If we have enough, we return the resulting list
if (result.Count == amount)
{
Log.Info("Selection completed successfully.");
return result;
}
}
}
}
//if there are no Daily Tests matching our criteria, or there weren't enough of them, we return either an empty
// list or those we found
int count = result.Count;
Log.Warn(count == 0 ? "No Daily Tests were found." : "Only " + count + " Daily Tests were found.");
return result;
}