{"id":324,"date":"2018-03-30T15:18:55","date_gmt":"2018-03-30T14:18:55","guid":{"rendered":"http:\/\/www.djhiro.at\/?p=324"},"modified":"2018-03-30T15:24:32","modified_gmt":"2018-03-30T14:24:32","slug":"fill-a-dictionary-with-properties-of-a-class","status":"publish","type":"post","link":"https:\/\/www.djhiro.at\/?p=324","title":{"rendered":"Fill a dictionary with properties of a class"},"content":{"rendered":"<p>Following scenario&#8230; you need to create a key\/value configuration file within a configuration class. Properties are the Keys and their value is the value ;). Values for the properties need to be assigned automaticly when the &#8220;configuration file&#8221; is loaded, in a way that the class can be extended with new properties and no new code needs to be added.<\/p>\n<p>One of the solutions I found, was to use a Singleton-Pattern with<\/p>\n<pre class=\"lang:c# decode:true\">Dictionary&lt;string, object&gt;<\/pre>\n<p>that holds all the property keys and values.<\/p>\n<p>Lets walk this through with a real life example. Nlog is used for logging. At the End you can see the whole class, but first let us go through everything step by step.<\/p>\n<p>First the properties:<\/p>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\" title=\"Properties\">public bool ConfigurationSet { get; set; }\r\npublic string RemoteIPAddress { get; set; }\r\npublic string RemotePort { get; set; }\r\npublic string LocalIPAddress { get; set; }\r\npublic string LocalPort { get; set; }\r\npublic bool TCP { get; set; }\r\npublic bool UDP { get; set; }\r\npublic bool Multicast { get; set; }\r\npublic bool GzipCompression { get; set; }\r\npublic string ReceiveBufferSize { get; set; }\r\npublic string MaxSegmentSize { get; set; }\r\npublic string SocketBufferSize { get; set; }\r\npublic string DateMatchGroup { get; set; }\r\npublic string TextAfterDateMatch { get; set; }\r\npublic string TextBeforeProviderMatchGroup { get; set; }\r\npublic string ProviderMatchGroup { get; set; }\r\npublic string TextBeforeXMLCallListMatchGroup { get; set; }\r\npublic string FullRegex { get; private set; }\r\npublic string CallListMatchGroup { get; set; }\r\npublic string ConfigurationPath\r\n{\r\n\tget\r\n\t{\r\n\t\treturn _configurationPath;\r\n\t}\r\n\tprivate set =&gt; _configurationPath = value;\r\n}\r\npublic string ConfigurationFile\r\n{\r\n\tget\r\n\t{\r\n\t\treturn _configurationFile;\r\n\t}\r\n\tprivate set =&gt; _configurationFile = value;\r\n}\r\npublic string ExtractionFileName { get; set; }\r\npublic string ExtractionFolder { get; set; }\r\npublic string MulticastSendTimeoutInMS { get; set; }<\/pre>\n<p>The &#8220;ConfigurationSet&#8221; Property is not used in the configuration file. It can be used for other parts of the program to find out if the configuration has been loaded and the properties have values.<\/p>\n<p>Then there is the Dictionary as &lt;string, object&gt; and the singleton with the private and static constructor, this is thread-safe!<\/p>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\">private static readonly object _locker = new object();\r\npublic Dictionary&lt;string, object&gt; ConfigurationItems { get; private set; }\r\nprivate static readonly ConfigurationHelper _configuration = new ConfigurationHelper();\r\npublic static ConfigurationHelper Configuration\r\n{\r\n\tget\r\n\t{\r\n\t\treturn _configuration;\r\n\t}\r\n\tprivate set\r\n\t{\r\n\t\tlock(_locker)\r\n\t\t{\r\n\t\t\t_configuration = value;\r\n\t\t\tMonitor.Pulse(_locker);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nprivate ConfigurationHelper() { }\r\n\r\nstatic ConfigurationHelper() { }<\/pre>\n<p>for more information on singletons, see: <a href=\"http:\/\/C-Sharp in Depth - Singleton\">http:\/\/csharpindepth.com\/Articles\/General\/Singleton.aspx<\/a><\/p>\n<p>The last Members are the Configurationfolder, the configurationfilename and the logger (nlog).<\/p>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\">private string _configurationPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @\"\\Reflection\\\";\r\nprivate string _configurationFile = \"reflection.config\";\r\nprivate static readonly Logger _log = LogManager.GetCurrentClassLogger();<\/pre>\n<p><!--nextpage--><\/p>\n<p>Next the functions:<\/p>\n<p>2 public functions, one to load the current configuration or to create a standard configuration is none has been found and the second one to save (write) the configuration.<\/p>\n<h4>Loading or Creating of the configuration File<\/h4>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\" title=\"Loading and or Creating the Configuration\">\/\/\/ &lt;summary&gt;\r\n\/\/\/ Loads the Confiugration if it exists, Creates a Standard-Configuration with default Values\r\n\/\/\/ if it does not exist\r\n\/\/\/ &lt;\/summary&gt;\r\npublic void LoadOrCreateConfiguration()\r\n{\r\n\t_log.Debug(\"--&gt; LoadOrCreateConfiguration\");\r\n\r\n\tif (!ConfigurationSet)\r\n\t{\r\n\t\tConfigurationItems = new Dictionary&lt;string, object&gt;();\r\n\t\tPropertiesToDictionary();\r\n\t\t_log.Trace(\"### Dictonary with the configuration items has been created\");\r\n\r\n\t\tif (ConfigurationExists())\r\n\t\t{\r\n\t\t\tReadConfiguration();\r\n\t\t\t_log.Debug(\"&lt;-- LoadOrCreateConfiguration\");\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tCreateConfiguration();\r\n\t\t\t_log.Debug(\"&lt;-- LoadOrCreateConfiguration\");\r\n\t\t}\r\n\t}\r\n}<\/pre>\n<p>First thing we do, we check if the configuration has been loaded alread (ConfigurationSet is false). Is it not loaded we create a new Dictionary and load all the properties without value into it (Function: PropertiesToDictionary(), we go through it in just a moment). If the configuration file exists, it will be loaded (Function: ReadConfiguration() ), if no file is found a &#8220;Standard&#8221;-configuration will be created (Function: CreateConfiguration()).<\/p>\n<h4>Saving \/ writing the Configurationfile<\/h4>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\" title=\"Saving and Writing the Configuration file\">\/\/\/ &lt;summary&gt;\r\n\/\/\/ Save a current Configuration\r\n\/\/\/ &lt;\/summary&gt;\r\npublic void SaveConfiuration()\r\n{\r\n\t_log.Debug(\"--&gt; SaveConfiguration\");\r\n\r\n\tCreateConfiguration();\r\n\r\n\t_log.Debug(\"&lt;-- Save Configuration\");\r\n}<\/pre>\n<p>Writing the file and &#8220;creating&#8221; the standard configuration is the same function, saving encapsulates the &#8220;CreateConfiguration&#8221; function.<\/p>\n<p>next are the private functions.<\/p>\n<p><!--nextpage--><\/p>\n<p>There are 7 private functions<\/p>\n<h4>Function: ConfigurationExists()<\/h4>\n<p>The ConfigurationExists function, just checks if the file exists or not<\/p>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\" title=\"Configuration is existing?\">\/\/\/ &lt;summary&gt;\r\n\/\/\/ Check if the Confiuration File exists\r\n\/\/\/ &lt;\/summary&gt;\r\n\/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\nprivate bool ConfigurationExists()\r\n{\r\n\t_log.Debug(\"&lt;--&gt; ConfigurationExists\");\r\n\r\n\treturn File.Exists(_configurationPath + _configurationFile);\r\n}<\/pre>\n<h4>Function: CreateConfiguration()<\/h4>\n<p>Within the Function it is first checked if the Configuration has been set, if not the Function &#8220;SetDefaultValues()&#8221; creates a set of standard values for the properties. Next we check if the Configuration exists, this is done because saving the normal configuration and creating a standard configuration is done through the same function.<\/p>\n<p>We iterate through the dictionary and write all the key-value Items into the configuration file.<\/p>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\" title=\"Creating and Saving the Configuration\">\/\/\/ &lt;summary&gt;\r\n\/\/\/ Create the Standard configuration with the property values\r\n\/\/\/ &lt;\/summary&gt;\r\nprivate void CreateConfiguration()\r\n{\r\n\t_log.Debug(\"--&gt; CreateStandardConfiguration\");\r\n\r\n\tif (!ConfigurationSet)\r\n\t\tSetDefautlValues();\r\n\tif (!ConfigurationExists())\r\n\t\tDirectory.CreateDirectory(_configurationPath);\r\n\r\n\tusing (FileStream fs = new FileStream(_configurationPath + _configurationFile, FileMode.OpenOrCreate, FileAccess.Write))\r\n\t{\r\n\t\tusing (StreamWriter sw = new StreamWriter(fs))\r\n\t\t{\r\n\t\t\tforeach (KeyValuePair&lt;string, object&gt; configItem in ConfigurationItems)\r\n\t\t\t{\r\n\t\t\t\tsw.WriteLine(configItem.Key + \"=\" + configItem.Value);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t_log.Debug(\"&lt;-- CreateStandardConfiguration: Created standard configuration and file: {0}\", _configurationPath + _configurationFile);\r\n}<\/pre>\n<h4>Function: SetDefaultValues()<\/h4>\n<p>This function just creates a set of default values, if no file has been found.<\/p>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\">\/\/\/ &lt;summary&gt;\r\n\/\/\/ Set Default Values for the Configuration\r\n\/\/\/ &lt;\/summary&gt;\r\nprivate void SetDefautlValues()\r\n{\r\n\t_log.Debug(\"--&gt; SetDefaultValues\");\r\n\r\n\tLocalIPAddress = \"10.254.0.101\";\r\n\tLocalPort = \"0\";\r\n\tRemoteIPAddress = \"10.254.0.133\";\r\n\tRemotePort = \"43238\";\r\n\r\n\tTCP = false;\r\n\tUDP = false;\r\n\tMulticast = true;\r\n\tGzipCompression = false;\r\n\r\n\tReceiveBufferSize = \"8192\";\r\n\tMaxSegmentSize = \"200\";\r\n\tSocketBufferSize = \"8388608\";\r\n\tMulticastSendTimeoutInMS = \"500\";\r\n\r\n\tDateMatchGroup = @\"(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3})\";\r\n\tTextAfterDateMatch = @\"(.*)\";\r\n\tTextBeforeProviderMatchGroup = @\"CallList from\";\r\n\tProviderMatchGroup = @\"(.*)\";\r\n\tTextBeforeXMLCallListMatchGroup = @\"\\\/MTP received. New Revision \\(\\d{1,9}\\):\";\r\n\tCallListMatchGroup = @\"(.*)\";\r\n\r\n\tFullRegex = DateMatchGroup + TextAfterDateMatch + TextBeforeProviderMatchGroup + ProviderMatchGroup + TextBeforeXMLCallListMatchGroup + CallListMatchGroup;\r\n\r\n\tExtractionFolder = @\"C:\\Temp\\\";\r\n\tExtractionFileName = @\"extraction.log\";\r\n\r\n\tConfigurationSet = true;\r\n\r\n\tPropertiesToDictionary();\r\n\r\n\t_log.Debug(\"&lt;-- SetDefaultValues\");\r\n}<\/pre>\n<h4>Function: ReadConfiguration()<\/h4>\n<p>The ReadConfiguration function opens a Filestream to the configuration file and reads all key-value pairs, line by line, every line is split and given to the &#8220;UpdateDictionaryValue&#8221;-Function.<\/p>\n<p>After all Dictionary Entries are updated, the Dictionary is transfered to the Singleton object, so it can be accessed by other parts of the program.<\/p>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\" title=\"Read the Configuration\">\/\/\/ &lt;summary&gt;\r\n\/\/\/ Read Configuration from Configuration File\r\n\/\/\/ &lt;\/summary&gt;\r\nprivate void ReadConfiguration()\r\n{\r\n\t_log.Debug(\"--&gt; ReadConfiguration\");\r\n\r\n\tusing (FileStream fileStream = new FileStream(_configurationPath + _configurationFile, FileMode.Open, FileAccess.Read))\r\n\t{\r\n\t\tusing (StreamReader streamreader = new StreamReader(fileStream))\r\n\t\t{\r\n\t\t\tstring configurationLine;\r\n\t\t\twhile (!streamreader.EndOfStream)\r\n\t\t\t{\r\n\t\t\t\tconfigurationLine = streamreader.ReadLine();\r\n\t\t\t\tconfigurationLine = configurationLine.Trim();\r\n\r\n\t\t\t\t\/\/=== Equals a Topic and can be ignored\r\n\t\t\t\tif (!configurationLine.Contains(\"===\"))\r\n\t\t\t\t{\r\n\t\t\t\t\tstring[] configItem = configurationLine.Split('=');\r\n\t\t\t\t\tUpdateDictionaryValue(configItem);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tConfigurationSet = true;\r\n\tConfigurationItems[nameof(ConfigurationSet)] = true;\r\n\r\n\tDictionaryToProperties();\r\n\r\n\t_log.Debug(\"&lt;-- ReadConfiguration\");\r\n}<\/pre>\n<h4>Function: UpdateDictionaryValue(configItem)<\/h4>\n<p>The Function checks if an configuration item is within the dictionary and if it finds it, updates the value for this particular item.<\/p>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\" title=\"Update Dictionary Item with Value\">\/\/\/ &lt;summary&gt;\r\n\/\/\/ Transfers the read configuration Item to the Property, so it can be accessed from outside\r\n\/\/\/ &lt;\/summary&gt;\r\n\/\/\/ &lt;param name=\"configItem\"&gt;String Array with Propertyname and Propertyvalue&lt;\/param&gt;\r\nprivate void UpdateDictionaryValue(string[] configItem)\r\n{\r\n\t_log.Debug(\"--&gt; TransformConfigurationItemToPropertyViaReflection: Configuration Item: {0}, Configuration Value: {1}\", configItem[0], configItem[1]);\r\n\r\n\tif (ConfigurationItems.ContainsKey(configItem[0]))\r\n\t\tConfigurationItems[configItem[0]] = configItem[1];\r\n\telse\r\n\t\t_log.Error(\"### Configuration Item with Key: {0} and Value: {1} couldn't be found\", configItem[0], configItem[1]);\r\n\r\n\t_log.Trace(\"&lt;-- TransformConfigurationItemToPropertyViaReflection\");\r\n}<\/pre>\n<p>Now to the last 2 private functions were all the magic happens, actually the refer to a new class, but we go there in just a minute.<\/p>\n<p>Funcion: PropertiesToDictionary()<\/p>\n<p>This function takes itself (this) and gets a Dictionary via a static class and reflections with all the properties as key-value pairs<\/p>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\" title=\"Properties to Dictionary\">\/\/\/ &lt;summary&gt;\r\n\/\/\/ Uses Reflection to get a dictionary of the properties\r\n\/\/\/ &lt;\/summary&gt;\r\nprivate void PropertiesToDictionary()\r\n{\r\n\t_log.Debug(\"--&gt; GenerateDictionaryFromProperties\");\r\n\r\n\tConfigurationItems = (Dictionary&lt;string, object&gt;)ObjectExtensions.ObjectToDictionary(this);\r\n\t_log.Debug(\"### Properties found {0}\", ConfigurationItems.Count);\r\n\r\n\t_log.Debug(\"&lt;-- GenerateDictionaryFromProperties\");\r\n}<\/pre>\n<h4>Function: DictionaryToProperties()<\/h4>\n<p>This function transfers all the Key-Value Pairs of the dictionary to the singleton for external excess.<\/p>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\">\/\/\/ &lt;summary&gt;\r\n\/\/\/ Transforms the Dictionary to the Singleton Properties\r\n\/\/\/ &lt;\/summary&gt;\r\nprivate void DictionaryToProperties()\r\n{\r\n\t_log.Debug(\"--&gt; DictionaryToProperties\");\r\n\r\n\tConfiguration = ObjectExtensions.ObjectFromDictionary&lt;ConfigurationHelper&gt;(ConfigurationItems);\r\n\r\n\t_log.Debug(\"&lt;-- DictionaryToProperties\");\r\n}<\/pre>\n<p><!--nextpage--><\/p>\n<p>Lets come to the most importan class in all this, the &#8220;ObjectExtensions&#8221; it has 2 functions, one the transfers all the properties of a given class into a IDictionary&lt;string,object&gt; and one that transfers all the Dictionary Key-Value pairs to a given class.<\/p>\n<h4>Function &#8220;ObjectFromDictionary&lt;t&gt;()&#8221;<\/h4>\n<p>The function takes a class and a Dictionary and tranfsers all the Key-Value pairs onto the properties of the given class.<\/p>\n<p>But be careful, Boolean, int, float, long, Arrays, Lists, etc. have to be cast as can be seen in the example. My Configuration Class uses a few booleans and their value is saved as string in the dictionary.<\/p>\n<p>If an item can not be transfered a &#8220;System.Reflection.TargetException: &#8216;Object does not match target type.'&#8221; is thrown!<\/p>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\" title=\"Object from Dictionary\"> public static T ObjectFromDictionary&lt;T&gt;(IDictionary&lt;string, object&gt; dict) where T:class\r\n{\r\n\t_log.Debug(\"--&gt; ObjectFromDictionary\");\r\n\r\n\tType myObjectType = typeof(T);\r\n\tT result = (T)Activator.CreateInstance(myObjectType);\r\n\tforeach (var item in dict)\r\n\t{\r\n\t\tif (item.Value.Equals(\"true\") || item.Value.Equals(\"True\"))\r\n\t\t\t\tmyObjectType.GetProperty(item.Key).SetValue(result, true, null);\r\n\t\telse if(item.Value.Equals(\"false\") || item.Value.Equals(\"False\"))\r\n\t\t\t\tmyObjectType.GetProperty(item.Key).SetValue(result, false, null);\r\n\t\telse\r\n\t\t\tmyObjectType.GetProperty(item.Key).SetValue(result, item.Value, null);\r\n\t}\r\n\r\n\t_log.Debug(\"&lt;-- ObjectFromDictionary\");\r\n\r\n\treturn result;\r\n}<\/pre>\n<h4>Function: ObjectToDictionary&lt;T&gt;()<\/h4>\n<p>This function takes a class and transfers all the properties into a dictionary in a key-value matter and then returns the dictionary for use.<\/p>\n<pre class=\"scroll:true minimize:true lang:c# decode:true\" title=\"Object to Dictionary\">public static IDictionary&lt;string, object&gt; ObjectToDictionary&lt;T&gt;(T item) where T:class\r\n{\r\n\tType myObjectType = item.GetType();\r\n\tIDictionary&lt;string, object&gt; dict = new Dictionary&lt;string, object&gt;();\r\n\tPropertyInfo[] properties = myObjectType.GetProperties();\r\n\tforeach (PropertyInfo property in properties)\r\n\t{\r\n\t\tvar value = property.GetValue(item, null);\r\n\t\tdict.Add(property.Name, value);\r\n\t}\r\n\treturn dict;\r\n}<\/pre>\n<p>Here you go.<\/p>\n<p>Idea and most of the reflection work was done on stackoverflow \ud83d\ude09<\/p>\n<p>Post on Stackoverflow: <a href=\"https:\/\/stackoverflow.com\/a\/4944155\">https:\/\/stackoverflow.com\/a\/4944155<\/a><\/p>\n<p>Thread on Stackoverflow: <a href=\"https:\/\/stackoverflow.com\/questions\/4943817\/mapping-object-to-dictionary-and-vice-versa\">https:\/\/stackoverflow.com\/questions\/4943817\/mapping-object-to-dictionary-and-vice-versa<\/a><\/p>\n<p>On the next page is the source-code of both classes \ud83d\ude42<\/p>\n<p><!--nextpage--><\/p>\n<h2>ConfigurationHelper-Class<\/h2>\n<pre class=\"scroll:true minimize:true lang:c# decode:true \" title=\"ConfigurationHelper Class\">using NLog;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.IO;\r\nusing System.Threading;\r\n\r\nnamespace Common.Libraries\r\n{\r\n    \/\/\/ &lt;summary&gt;\r\n    \/\/\/ Handels Local File Configuration\r\n    \/\/\/ &lt;\/summary&gt;\r\n    public sealed class ConfigurationHelper\r\n    {\r\n        private string _configurationPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @\"\\Reflection\\\";\r\n        private string _configurationFile = \"reflection.config\";\r\n        private static readonly Logger _log = LogManager.GetCurrentClassLogger();\r\n        private static readonly object _locker = new object();\r\n\r\n        public Dictionary&lt;string, object&gt; ConfigurationItems { get; private set; }\r\n        private static ConfigurationHelper _configuration = new ConfigurationHelper();\r\n        public static ConfigurationHelper Configuration\r\n        {\r\n            get\r\n            {\r\n                return _configuration;\r\n            }\r\n            private set\r\n            {\r\n                lock(_locker)\r\n                {\r\n                    _configuration = value;\r\n                    Monitor.Pulse(_locker);\r\n                }\r\n            }\r\n        }\r\n\r\n        private ConfigurationHelper() { }\r\n\r\n        static ConfigurationHelper() { }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Loads the Confiugration if it exists, Creates a Standard-Configuration with default Values\r\n        \/\/\/ if it does not exist\r\n        \/\/\/ &lt;\/summary&gt;\r\n        public void LoadOrCreateConfiguration()\r\n        {\r\n            _log.Debug(\"--&gt; LoadOrCreateConfiguration\");\r\n\r\n            if (!ConfigurationSet)\r\n            {\r\n                ConfigurationItems = new Dictionary&lt;string, object&gt;();\r\n                PropertiesToDictionary();\r\n                _log.Trace(\"### Dictonary with the configuration items has been created\");\r\n\r\n                if (ConfigurationExists())\r\n                {\r\n                    ReadConfiguration();\r\n                    _log.Debug(\"&lt;-- LoadOrCreateConfiguration\");\r\n                }\r\n                else\r\n                {\r\n                    CreateConfiguration();\r\n                    _log.Debug(\"&lt;-- LoadOrCreateConfiguration\");\r\n                }\r\n            }\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Save a current Configuration\r\n        \/\/\/ &lt;\/summary&gt;\r\n        public void SaveConfiuration()\r\n        {\r\n            _log.Debug(\"--&gt; SaveConfiguration\");\r\n\r\n            CreateConfiguration();\r\n\r\n            _log.Debug(\"&lt;-- Save Configuration\");\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Create the Standard configuration with the property values\r\n        \/\/\/ &lt;\/summary&gt;\r\n        private void CreateConfiguration()\r\n        {\r\n            _log.Debug(\"--&gt; CreateStandardConfiguration\");\r\n\r\n            if (!ConfigurationSet)\r\n                SetDefautlValues();\r\n            if (!ConfigurationExists())\r\n                Directory.CreateDirectory(_configurationPath);\r\n\r\n            using (FileStream fs = new FileStream(_configurationPath + _configurationFile, FileMode.OpenOrCreate, FileAccess.Write))\r\n            {\r\n                using (StreamWriter sw = new StreamWriter(fs))\r\n                {\r\n                    foreach (KeyValuePair&lt;string, object&gt; configItem in ConfigurationItems)\r\n                    {\r\n                        sw.WriteLine(configItem.Key + \"=\" + configItem.Value);\r\n                    }\r\n                }\r\n            }\r\n\r\n            _log.Debug(\"&lt;-- CreateStandardConfiguration: Created standard configuration and file: {0}\", _configurationPath + _configurationFile);\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Set Default Values for the Configuration\r\n        \/\/\/ &lt;\/summary&gt;\r\n        private void SetDefautlValues()\r\n        {\r\n            _log.Debug(\"--&gt; SetDefaultValues\");\r\n\r\n            LocalIPAddress = \"10.254.0.101\";\r\n            LocalPort = \"0\";\r\n            RemoteIPAddress = \"10.254.0.133\";\r\n            RemotePort = \"43238\";\r\n\r\n            TCP = false;\r\n            UDP = false;\r\n            Multicast = true;\r\n            GzipCompression = false;\r\n\r\n            ReceiveBufferSize = \"8192\";\r\n            MaxSegmentSize = \"200\";\r\n            SocketBufferSize = \"8388608\";\r\n            MulticastSendTimeoutInMS = \"500\";\r\n\r\n            DateMatchGroup = @\"(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3})\";\r\n            TextAfterDateMatch = @\"(.*)\";\r\n            TextBeforeProviderMatchGroup = @\"CallList from\";\r\n            ProviderMatchGroup = @\"(.*)\";\r\n            TextBeforeXMLCallListMatchGroup = @\"\\\/MTP received. New Revision \\(\\d{1,9}\\):\";\r\n            CallListMatchGroup = @\"(.*)\";\r\n\r\n            FullRegex = DateMatchGroup + TextAfterDateMatch + TextBeforeProviderMatchGroup + ProviderMatchGroup + TextBeforeXMLCallListMatchGroup + CallListMatchGroup;\r\n\r\n            ExtractionFolder = @\"C:\\Temp\\\";\r\n            ExtractionFileName = @\"extraction.log\";\r\n\r\n            ConfigurationSet = true;\r\n\r\n            PropertiesToDictionary();\r\n\r\n            _log.Debug(\"&lt;-- SetDefaultValues\");\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Read Configuration from Configuration File\r\n        \/\/\/ &lt;\/summary&gt;\r\n        private void ReadConfiguration()\r\n        {\r\n            _log.Debug(\"--&gt; ReadConfiguration\");\r\n\r\n            using (FileStream fileStream = new FileStream(_configurationPath + _configurationFile, FileMode.Open, FileAccess.Read))\r\n            {\r\n                using (StreamReader streamreader = new StreamReader(fileStream))\r\n                {\r\n                    string configurationLine;\r\n                    while (!streamreader.EndOfStream)\r\n                    {\r\n                        configurationLine = streamreader.ReadLine();\r\n                        configurationLine = configurationLine.Trim();\r\n\r\n                        string[] configItem = configurationLine.Split('=');\r\n                        UpdateDictionaryValue(configItem);\r\n                    }\r\n                }\r\n            }\r\n            ConfigurationSet = true;\r\n            ConfigurationItems[nameof(ConfigurationSet)] = true;\r\n\r\n            DictionaryToProperties();\r\n\r\n            _log.Debug(\"&lt;-- ReadConfiguration\");\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Transfers the read configuration Item to the Property, so it can be accessed from outside\r\n        \/\/\/ &lt;\/summary&gt;\r\n        \/\/\/ &lt;param name=\"configItem\"&gt;String Array with Propertyname and Propertyvalue&lt;\/param&gt;\r\n        private void UpdateDictionaryValue(string[] configItem)\r\n        {\r\n            _log.Debug(\"--&gt; TransformConfigurationItemToPropertyViaReflection: Configuration Item: {0}, Configuration Value: {1}\", configItem[0], configItem[1]);\r\n\r\n            if (ConfigurationItems.ContainsKey(configItem[0]))\r\n                ConfigurationItems[configItem[0]] = configItem[1];\r\n            else\r\n                _log.Error(\"### Configuration Item with Key: {0} and Value: {1} couldn't be found\", configItem[0], configItem[1]);\r\n\r\n            _log.Trace(\"&lt;-- TransformConfigurationItemToPropertyViaReflection\");\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Uses Reflection to get a dictionary of the properties\r\n        \/\/\/ &lt;\/summary&gt;\r\n        private void PropertiesToDictionary()\r\n        {\r\n            _log.Debug(\"--&gt; GenerateDictionaryFromProperties\");\r\n\r\n            ConfigurationItems = (Dictionary&lt;string, object&gt;)ObjectExtensions.ObjectToDictionary(this);\r\n            _log.Debug(\"### Properties found {0}\", ConfigurationItems.Count);\r\n\r\n            _log.Debug(\"&lt;-- GenerateDictionaryFromProperties\");\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Transforms the Dictionary to the Singleton Properties\r\n        \/\/\/ &lt;\/summary&gt;\r\n        private void DictionaryToProperties()\r\n        {\r\n            _log.Debug(\"--&gt; DictionaryToProperties\");\r\n\r\n            Configuration = ObjectExtensions.ObjectFromDictionary&lt;ConfigurationHelper&gt;(ConfigurationItems);\r\n\r\n            _log.Debug(\"&lt;-- DictionaryToProperties\");\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Check if the Confiuration File exists\r\n        \/\/\/ &lt;\/summary&gt;\r\n        \/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\n        private bool ConfigurationExists()\r\n        {\r\n            _log.Debug(\"&lt;--&gt; ConfigurationExists\");\r\n\r\n            return File.Exists(_configurationPath + _configurationFile);\r\n        }\r\n\r\n        #region Properties\r\n\r\n        public bool ConfigurationSet { get; set; }\r\n        public string RemoteIPAddress { get; set; }\r\n        public string RemotePort { get; set; }\r\n        public string LocalIPAddress { get; set; }\r\n        public string LocalPort { get; set; }\r\n        public bool TCP { get; set; }\r\n        public bool UDP { get; set; }\r\n        public bool Multicast { get; set; }\r\n        public bool GzipCompression { get; set; }\r\n        public string ReceiveBufferSize { get; set; }\r\n        public string MaxSegmentSize { get; set; }\r\n        public string SocketBufferSize { get; set; }\r\n        public string DateMatchGroup { get; set; }\r\n        public string TextAfterDateMatch { get; set; }\r\n        public string TextBeforeProviderMatchGroup { get; set; }\r\n        public string ProviderMatchGroup { get; set; }\r\n        public string TextBeforeXMLCallListMatchGroup { get; set; }\r\n        public string FullRegex { get; private set; }\r\n        public string CallListMatchGroup { get; set; }\r\n        public string ConfigurationPath\r\n        {\r\n            get\r\n            {\r\n                return _configurationPath;\r\n            }\r\n            private set =&gt; _configurationPath = value;\r\n        }\r\n        public string ConfigurationFile\r\n        {\r\n            get\r\n            {\r\n                return _configurationFile;\r\n            }\r\n            private set =&gt; _configurationFile = value;\r\n        }\r\n        public string ExtractionFileName { get; set; }\r\n        public string ExtractionFolder { get; set; }\r\n        public string MulticastSendTimeoutInMS { get; set; }\r\n\r\n        #endregion properties\r\n    }\r\n}<\/pre>\n<h2>ObjectExtensions Class<\/h2>\n<pre class=\"scroll:true minimize:true lang:c# decode:true \" title=\"Object Extensions\">using NLog;\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.Reflection;\r\n\r\nnamespace Common.Libraries\r\n{\r\n    public static class ObjectExtensions\r\n    {\r\n        private static readonly Logger _log = LogManager.GetCurrentClassLogger();\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Transfer a given dicionary to a given class\r\n        \/\/\/ &lt;\/summary&gt;\r\n        \/\/\/ &lt;typeparam name=\"T\"&gt;Class with Properties to be mapped&lt;\/typeparam&gt;\r\n        \/\/\/ &lt;param name=\"dict\"&gt;Dictionary for Property-mapping&lt;\/param&gt;\r\n        \/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\n        public static T ObjectFromDictionary&lt;T&gt;(IDictionary&lt;string, object&gt; dict) where T:class\r\n        {\r\n            _log.Debug(\"--&gt; ObjectFromDictionary\");\r\n\r\n            Type myObjectType = typeof(T);\r\n            T result = (T)Activator.CreateInstance(myObjectType);\r\n            foreach (var item in dict)\r\n            {\r\n                \/\/TODO optimize this if!\r\n                if (item.Value.Equals(\"true\") || item.Value.Equals(\"True\"))\r\n                        myObjectType.GetProperty(item.Key).SetValue(result, true, null);\r\n                else if(item.Value.Equals(\"false\") || item.Value.Equals(\"False\"))\r\n                        myObjectType.GetProperty(item.Key).SetValue(result, false, null);\r\n                else\r\n                    myObjectType.GetProperty(item.Key).SetValue(result, item.Value, null);\r\n            }\r\n\r\n            _log.Debug(\"&lt;-- ObjectFromDictionary\");\r\n\r\n            return result;\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Transfers a given class and the properties to a Dictionary\r\n        \/\/\/ &lt;\/summary&gt;\r\n        \/\/\/ &lt;typeparam name=\"T\"&gt;Classtype to be transfered&lt;\/typeparam&gt;\r\n        \/\/\/ &lt;param name=\"item\"&gt;Class-Object to be transfered&lt;\/param&gt;\r\n        \/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\n        public static IDictionary&lt;string, object&gt; ObjectToDictionary&lt;T&gt;(T item) where T:class\r\n        {\r\n            Type myObjectType = item.GetType();\r\n            IDictionary&lt;string, object&gt; dict = new Dictionary&lt;string, object&gt;();\r\n            PropertyInfo[] properties = myObjectType.GetProperties();\r\n            foreach (PropertyInfo property in properties)\r\n            {\r\n                var value = property.GetValue(item, null);\r\n                dict.Add(property.Name, value);\r\n            }\r\n            return dict;\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>If you have any Suggestions or find a better soluation, just write a comment \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Following scenario&#8230; you need to create a key\/value configuration file within a configuration class. Properties are the Keys and their value is the value ;). Values for the properties need to be assigned automaticly when the &#8220;configuration file&#8221; is loaded, &hellip; <a href=\"https:\/\/www.djhiro.at\/?p=324\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":45,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[140,66,76,3,78,122],"tags":[90,143,144,142,141],"class_list":["post-324","post","type-post","status-publish","format-standard","hentry","category-c","category-pc","category-programming","category-sonstiges","category-wissen","category-work","tag-c","tag-dictionary","tag-object","tag-reflection","tag-singleton"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.djhiro.at\/index.php?rest_route=\/wp\/v2\/posts\/324","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.djhiro.at\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.djhiro.at\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.djhiro.at\/index.php?rest_route=\/wp\/v2\/users\/45"}],"replies":[{"embeddable":true,"href":"https:\/\/www.djhiro.at\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=324"}],"version-history":[{"count":10,"href":"https:\/\/www.djhiro.at\/index.php?rest_route=\/wp\/v2\/posts\/324\/revisions"}],"predecessor-version":[{"id":334,"href":"https:\/\/www.djhiro.at\/index.php?rest_route=\/wp\/v2\/posts\/324\/revisions\/334"}],"wp:attachment":[{"href":"https:\/\/www.djhiro.at\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=324"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.djhiro.at\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=324"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.djhiro.at\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=324"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}