I have created helper class for configuration validation, the main purpose is to find any human "errors" in the configuration for the app.
the case is that any type of "message" can be configured in more then one place, the application is ok with that and do no not limit this, in some very rare cases this is needed but for most this will cause problems.
with that said i still would like to prompt the warnings.
In the app config there can be unlimited amount of "managers" that each can hold list of "messages" there are also two types of them but that is not so important.
This is my draft of the class so far, it works but i feel this is very slow and can be done better or at least i am sure there are places to "fix" a little.
public static class ConfigurationValidator
{
public static void ValidateConfiguration(Configuration configuration)
{
if (configuration != null)
{
try
{
// Create Temp dictionary for validation.
Dictionary<string, List<string>> tempDictionary = new Dictionary<string, List<string>>();
Dictionary<string, List<string>> duplicatesList = new Dictionary<string, List<string>>();
// Fill the temp Dictionary for validation.
foreach (var player in configuration.PlayerManager.Players)
{
List<string> lst = new List<string>(); // list of messages.
for (int i = 0; i < player.Messages.Count; i++)
{
lst.Add(player.Messages[i].Type);
}
tempDictionary.Add(player.PlayerName, lst); // list name + list of messages.
}
FindDuplicates(tempDictionary, ref duplicatesList);
// clear for next set of validation.
tempDictionary.Clear();
foreach (var reciver in configuration.ReceiverManager.Receivers)
{
List<string> lst = new List<string>();
for (int i = 0; i < reciver.Messages.Count; i++)
{
lst.Add(reciver.Messages[i].Type);
}
tempDictionary.Add(reciver.ReceiverName, lst);
}
FindDuplicates(tempDictionary, ref duplicatesList);
PrintDuplicates(duplicatesList);
}
catch (Exception Ex)
{
Log.Instance.Error(Ex.Message, Ex);
}
}
else
{
Log.Instance.Warn($"Cannot validate empty configuration.");
}
}
private static void FindDuplicates(Dictionary<string, List<string>> data, ref Dictionary<string, List<string>> duplicatesList)
{
// find duplicates
var dupes = new HashSet<string>(
from list1 in data.Values
from list2 in data.Values
where list1 != list2
from item in list1.Intersect(list2)
select item);
foreach (var list in data.Values)
{
foreach (var message in dupes)
{
if (list.Contains(message))
{
var listName = data.FirstOrDefault(x => x.Value == list).Key;
List<string> value = (duplicatesList.TryGetValue(message, out List<string> index) ? duplicatesList[message] : null);
if (value == null)
{
duplicatesList.Add(message, new List<string>());
duplicatesList[message].Add(listName);
}
else
{
duplicatesList[message].Add(listName);
}
}
}
}
}
private static void PrintDuplicates(Dictionary<string, List<string>> duplicatesList)
{
if (duplicatesList == null || duplicatesList.Count <= 0)
{
Log.Instance.Info("Configuration validation was OK! no duplicates were found.");
return;
}
Log.Instance.Error($"Configuration validation found duplicate messages in configuration!!!");
Log.Instance.Warn($"This could lead to not accurate recording or playing please fix before using the DDS Recorder.");
foreach (var key in duplicatesList)
{
Log.Instance.Warn($"The Message: [{key.Key}] is duplicated in this lists: ");
foreach (var listName in key.Value)
{
Log.Instance.Warn($" Name: [{listName}]");
}
}
}
intersect
return a collection of duplicates in a straight forward way? Most of the rest of the code seems superfluous in that case. \$\endgroup\$intersect
does that and i am using it there but i also needed to know from what "players" the duplicate comes from and not only the duplicate itself. \$\endgroup\$