Live Update Configuration Manager .Net Core
For the Resgrid Open Source CAD system, I have a need to set configuration values normally managed by the configuration manager from an outside system. The requirement due to a centralized JSON config file that users can manage that flows through all the parts of the Computer Aided Dispatch system, instead of having to update and manage a half dozen config files.
Recently I’ve started migrating Resgrid from the Full .Net 4.7 Framework to .Net Standard and .Net Core 3.1. When I did the Reflection code I was using no longer worked, the element and collection fields were null and threw an error.
Full .Net Framework Version
var settings = ConfigurationManager.ConnectionStrings; var element = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic); var collection = typeof(ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic); element.SetValue(settings, false); collection.SetValue(settings, false); if (!configResult) settings.Add(new ConnectionStringSettings("ResgridContext", Configuration["ConnectionStrings:ResgridContext"])); else settings.Add(new ConnectionStringSettings("ResgridContext", DataConfig.ConnectionString)); collection.SetValue(settings, true); element.SetValue(settings, true);
The above code worked for all the .Net Framework’s I had been using it for, I believe 4+, but stopped working in .Net Core. As .Net Core was written from the ground up, I’m pretty sure the Read Only field had changed, or that the properties of the field may have changed.
.Net Core Version
var settings = ConfigurationManager.ConnectionStrings; var element = typeof(ConfigurationElement).GetField("_readOnly", BindingFlags.Instance | BindingFlags.NonPublic); var collection = typeof(ConfigurationElementCollection).GetField("_readOnly", BindingFlags.Instance | BindingFlags.NonPublic); element.SetValue(settings, false); collection.SetValue(settings, false); // Modify the settings here settings.Add(new ConnectionStringSettings("ResgridContext", DataConfig.ConnectionString)); collection.SetValue(settings, true); element.SetValue(settings, true);
The code is structured the same, but with the changed in .Net Core they changed the read only flag name, which was actually two, you can see in the .Net Framework 4.7 version it was ‘_bReadyOnly’ and ‘bReadOnly’ now in .Net Core the read only flag is ‘_readOnly’ for both objects. After this change the code worked correctly.
So, how did I find the updated field name? Reflection.
var element = typeof(ConfigurationElement).GetFields(BindingFlags.Instance | BindingFlags.NonPublic); var collection = typeof(ConfigurationElementCollection).GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
In the code above, instead of calling ‘GetField’ I called ‘GetFields’ which returned an array of elements, on debugging I looked through that and find the correct name for the Read Only field for each object.
Hope this helps you out!
I’m the Founder of Resgrid an open source computer aided dispatch (CAD) solution for First Responders, Industrial and Business environments. If you or someone you know is part of a first responder organization like volunteer fire departments, career fire departments, EMS, search and rescue, CERT, public safety or disaster relief organizations check Resgrid out!