Довольно старый вопрос, но просто игра с решением этой проблемы. Это похоже на подход Саймона Мурье (который мне нравится больше в некотором смысле - менее хакерский), но означает, что любой код, который вызывает System.Configuration.ConfigurationManager.GetSection()
, продолжит работать без необходимости изменять их для использования статического метода, поэтому может привести к меньшему количеству кода изменить в целом.
Первое основное замечание: я понятия не имею, работает ли это с вложенными разделами, но я почти уверен, что это не так. Практически основным предупреждением является то, что для него требуются изменения в классе раздела конфигурации, поэтому вы можете использовать его только с пользовательскими разделами, исходный код которых у вас есть (и разрешено изменять!)
Второй и MAIN CAVEAT заключается в том, что я просто играю с этим, я не использую его ни в разработке, ни, безусловно, в производстве, а просто размазываю свой собственный код поверх базовой функциональности, такой как это может иметь эффекты, которые не проявляются в моем примере. Используйте на свой страх и риск .
(Сказав это, я тестирую его на сайте Umbraco, так что происходит множество других разделов конфигурации, и они все еще работают, так что я думаю, что это не имеет сразу ужасных эффектов)
РЕДАКТИРОВАТЬ: Это .NET 4, а не 3,5, как в оригинальном вопросе. Не знаю, будет ли это иметь значение.
Итак, вот код, довольно простой, просто переопределите DeserializeSection
для использования средства чтения XML, которое загружается из базы данных.
public class TestSettings : ConfigurationSection
{
protected override void DeserializeSection(System.Xml.XmlReader reader)
{
using (DbConnection conn = /* Get an open database connection from whatever provider you are using */)
{
DbCommand cmd = conn.CreateCommand();
cmd.CommandText = "select ConfigFileContent from Configuration where ConfigFileName = @ConfigFileName";
DbParameter p = cmd.CreateParameter();
p.ParameterName = "@ConfigFileName";
p.Value = "TestSettings.config";
cmd.Parameters.Add(p);
String xml = (String)cmd.ExecuteScalar();
using(System.IO.StringReader sr = new System.IO.StringReader(xml))
using (System.Xml.XmlReader xr = System.Xml.XmlReader.Create(sr))
{
base.DeserializeSection(xr);
}
}
}
// Below is all your normal existing section code
[ConfigurationProperty("General")]
public GeneralElement General { get { return (GeneralElement)base["General"]; } }
[ConfigurationProperty("UI")]
public UIElement UI { get { return (UIElement)base["UI"]; } }
...
...
}
Я использую ASP.Net, поэтому, чтобы он заработал, вам нужно web.config
, но тогда, в любом случае, мне нужно где-нибудь для строк подключения, или я вообще не собираюсь подключаться к базе данных.
Ваш пользовательский раздел должен быть определен как обычный в <configSections/>
; ключом к выполнению этой работы является размещение пустого элемента вместо ваших обычных настроек; вместо <TestSettings configSource="..."/>
или встроенных настроек, просто введите <TestSettings/>
Затем диспетчер конфигурации загрузит все разделы, увидит существующий элемент <TestSettings/>
и десериализует его, после чего ударит по переопределению и вместо этого загрузит XML из базы данных.
ПРИМЕЧАНИЕ : при десериализации ожидается фрагмент документа (он будет вызываться, когда читатель уже находится на узле), а не целый документ, поэтому, если ваши разделы хранятся в отдельных файлах, вы сначала необходимо удалить объявление <?xml ?>
, иначе вы получите Expected to find an element
.