/// <summary> /// Build dependency injection /// </summary> /// <param name="fileOption"></param> /// <param name="solverOption"></param> /// <returns></returns> public static IServiceProvider BuildDI(CommandOption fileOption, CommandOption solverOption) { // Build configuration var configuration = new ConfigurationBuilder() .SetBasePath(AppContext.BaseDirectory) .AddJsonFile("mazesettings.json", false) .Build(); var services = new ServiceCollection(); // Add logging var logger = new LoggerFactory() .AddFile("Logs/mazeapp-{Date}.log") .AddConsole() .AddDebug(minLevel: LogLevel.Trace); services.AddSingleton(logger).AddLogging(); // Load settings var settings = new MazeSettings(); configuration.GetSection("Maze").Bind(settings); if ((fileOption != null) && fileOption.HasValue()) { settings.MazeFile = fileOption.Value(); } if ((solverOption != null) && solverOption.HasValue()) { settings.MazeSolver = solverOption.Value(); } try { // validate settings Validations.ValidateConfiguration(settings); } catch (InvalidConfigurationParameterException e) { logger.CreateLogger <Program>().LogError(e, e.Message); throw; } // Add settings services.AddSingleton <MazeSettings>(settings); // Add runner class services.AddTransient <Interfaces.IMazeGrid, Maze.MazeGrid>(); // Add loader class services.AddTransient <Interfaces.IMazeLoader, Loaders.MazeTextLoader>(); // Add solver classes switch (settings.MazeSolver) { case "BFS": services.AddTransient <Interfaces.IMazeSolver, BFSGraphSolver>(); break; case "BFSR": services.AddTransient <Interfaces.IMazeSolver, BFSRecursiveGraphSolver>(); break; case "DFS": services.AddTransient <Interfaces.IMazeSolver, DFSGraphSolver>(); break; case "DFSR": services.AddTransient <Interfaces.IMazeSolver, DFSRecursiveGraphSolver>(); break; case "DJK": services.AddTransient <Interfaces.IMazeSolver, DijkstraGraphSolver>(); break; default: services.AddTransient <Interfaces.IMazeSolver, BFSGraphSolver>(); break; } // register a factory to return a solver from settings var serviceProvider = services.BuildServiceProvider(); return(serviceProvider); }
/// <summary> /// Validates App Configuration parameters /// </summary> /// <param name="settings"></param> public static void ValidateConfiguration(MazeSettings settings) { var properties = settings.GetType().GetTypeInfo().DeclaredProperties; // check for null , 0 or negative int and throw on invalid foreach (var property in properties) { if (property.PropertyType == typeof(string)) { string val = (string)property.GetValue(settings); if (string.IsNullOrEmpty(val)) { throw new InvalidConfigurationParameterException(property.Name, "Parameter can not be Null or Empty"); } } else if (property.PropertyType == typeof(int)) { int?val = (int)property.GetValue(settings); // we require a minimum of 2x2 if ((val ?? 0) <= 1) { throw new InvalidConfigurationParameterException(property.Name, "Parameter can not be Null or smalle than 2"); } } } // nice, now lets check the characters var validList = new List <string>(); if (settings.OpenChar.Length > 1) { throw new InvalidConfigurationParameterException("OpenChar", "Parameter is longer than one character"); } validList.Add(settings.OpenChar); if (settings.WallChar.Length > 1 || validList.Contains(settings.WallChar)) { throw new InvalidConfigurationParameterException("WallChar", "Parameter is longer than one character or already in use"); } validList.Add(settings.WallChar); if (settings.StartChar.Length > 1 || validList.Contains(settings.StartChar)) { throw new InvalidConfigurationParameterException("StartChar", "Parameter is longer than one character or already in use"); } validList.Add(settings.StartChar); if (settings.FinishChar.Length > 1 || validList.Contains(settings.FinishChar)) { throw new InvalidConfigurationParameterException("FinishChar", "Parameter is longer than one character or already in use"); } // clean up validList.Clear(); }