Friday, 28 February 2020

Strongly typed ConfigurationManager in .NET Framework

Handling configuration files in .NET Framework is often tedious. You retrieve the app setting as a string and must then parse it out. Dont you wish we could have a generic method to get a strongly typed app setting instead and spare ourselves with some code ? Sure you can!

using System;
using System.ComponentModel;
using System.Configuration;

namespace Hemit.OpPlan.Common.Extensions
{

    /// <summary>
    /// Utility methods for ConfigurationManager. Also included methods for handling OpenExeConfiguration (running process configuration, for example in tests and installers)
    /// </summary>
    public static class ConfigurationManagerWrapper
    {
        /// <summary>
        /// Sets an appsetting for the exe configuration
        /// </summary>
        /// <param name="appsetting"></param>
        /// <param name="value"></param>
        public static void SetAppsettingForExecConfiguration(string appsetting, object value)
        {
            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            config.AppSettings.Settings[appsetting].Value = Convert.ToString(value);
            config.Save(ConfigurationSaveMode.Modified);
        }

        /// <summary>
        /// Sets an appsetting for the exe configuration
        /// </summary>
        /// <param name="appsetting"></param>
        /// <param name="value"></param>
        public static string GetAppsettingExecConfiguration(string appsetting, object value)
        {
            return ConfigurationManager.AppSettings[appsetting];
        }

        /// <summary>
        /// Sets an appsetting for the exe configuration
        /// </summary>
        /// <param name="appsetting"></param>
        /// <param name="value"></param>
        public static void SetAppsettingForConfiguration(string appsetting, object value)
        {
            ConfigurationManager.AppSettings[appsetting] = Convert.ToString(value);
        }

        /// <summary>
        /// Sets an appsetting for the exe configuration
        /// </summary>
        /// <param name="appsetting"></param>
        /// <param name="value"></param>
        public static string GetAppsettingForExecConfiguration(string appsetting, object value)
        {
            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            return config.AppSettings.Settings[appsetting].Value;
        }


        /// <summary>
        /// Use this extension method to get a strongly typed app setting from the configuration file.
        /// Returns app setting in configuration file if key found and tries to convert the value to a specified type. In case this fails, the fallback value
        /// or if NOT specified - default value - of the app setting is returned
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="appsettingKey"></param>
        /// <param name="fallback"></param>
        /// <returns></returns>
        public static T GetAppsetting<T>(string appsettingKey, T fallback = default(T))
        {
            string val = ConfigurationManager.AppSettings[appsettingKey] ?? "";
            if (!string.IsNullOrEmpty(val))
            {
                try
                {
                    Type typeDefault = typeof(T);
                    var converter = TypeDescriptor.GetConverter(typeof(T));
                    return converter.CanConvertFrom(typeof(string)) ? (T)converter.ConvertFrom(val) : fallback;
                }
                catch (Exception err)
                {
                    Console.WriteLine(err); //Swallow exception
                    return fallback;
                }
            }
            return fallback;
        }

    }
}



Thursday, 20 February 2020

Generic method ShouldAll for FluentAssertions

This is a simple etension method for Fluent Assertions called ShouldAll that can be run on a collection and you can pass in your predicate of your choice and see the output. Consider this unit test:


         var oneyearPeriodComparions = new []
            {
                new ReferencePeriodComparisonResult { ReferencePeriod = reportPeriod2017 , CalculatedPeriod = calculatedReportPeriod2017.First() },
                new ReferencePeriodComparisonResult { ReferencePeriod = reportPeriod2017 , CalculatedPeriod = calculatedReportPeriod2017.Last()},
                new ReferencePeriodComparisonResult { ReferencePeriod = reportPeriod2018 , CalculatedPeriod = calculatedReportPeriod2018.First()},
                new ReferencePeriodComparisonResult { ReferencePeriod = reportPeriod2018 , CalculatedPeriod = calculatedReportPeriod2018.Last() },
                new ReferencePeriodComparisonResult { ReferencePeriod = reportPeriod2019 , CalculatedPeriod = calculatedReportPeriod2019.First() },
                new ReferencePeriodComparisonResult { ReferencePeriod = reportPeriod2019 , CalculatedPeriod = calculatedReportPeriod2019.Last() }
            };

            oneyearPeriodComparions.ShouldAll(comparison => comparison.CalculatedPeriod.ReportPeriodStartDateAndEndDateIsEqualTo(comparison.ReferencePeriod), outputPassingTests:true);


This uses this extension test for Fluent Assertions:

using FluentAssertions;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace SomeAcme.SomeLib
{

    public static class FluentAssertionsExtensions
    {

        /// <summary>
        /// Inspects that all tests are passing for given collection and given predicate
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="instances"></param>
        /// <param name="predicate"></param>
        /// <param name="outputFailingTests"></param>
        public static void ShouldAll<T>(this IEnumerable<T> instances, Expression<Func<T, bool>> predicate, bool outputFailingTests = true, bool outputPassingTests = false)
        {
            foreach (var instance in instances)
            {
                var isTestPassing = predicate.Compile().Invoke(instance);
                if (!isTestPassing && outputFailingTests || outputPassingTests)
                    Console.WriteLine($@"Test Running against object: {instance} Test Pass?:{isTestPassing}");
                isTestPassing.Should().Be(true);
            }
        }
    }

}