我试图在配置文件中使用实体定义来简化开发、qa、uat和生产版本之间的差异。以下是配置文件开头的示例:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE configuration [
<!ENTITY MyStorageLocation "\\MyServer\MyStorageFolder">
<!ENTITY MyDatabaseServer "devdb01">
]>
<configuration>
<configSections>
<section name="MyCustomSection" type="MyCustomSectionHandler,MyAssembly"/>
...
</configSections>
<connectionStrings>
<add name="MyConnectionString" providerName="System.Data.SqlClient" connectionString="Server=&MyDatabaseServer;;Database=MyDatabase;"/>
</connectionStrings>
...
<MyCustomSection>&MyStorageLocation;</MyCustomSection>
</configuration>
这似乎工作得很好,既然它是完全有效的XML,那么为什么不呢?只要我在一个自定义配置节中不使用这些实体中的任何一个,最后我将在该节上调用configurationmanager.getSection()。在连接字符串中使用“mydatabaseserver”实体不会导致任何问题。在提供的示例中,只要我不在myCustomSection元素中使用“myStorageLocation”实体,然后只在调用configurationManager.getSection()请求自定义节时遇到错误,一切都将正常工作。
我最好的猜测是,configurationmanager类正在获取元素的原始源并尝试将其加载为xml,而忽略整个xml文件的声明实体。有没有更好的方法来做到这一点,不重新编码自定义配置节,以支持对设置的引用,而不是许多绝对设置?
我收到的错误是:
2009-01-27 14:00:53,474 [11936] ERROR MyCustomWindowsService [(null)] - Errors starting service -- shutting down
System.Configuration.ConfigurationErrorsException: Reference to undeclared entity 'MyStorageLocation'. Line 183, position 19. (D:\...\MyCustomWindowsService.exe.config line 183) ---> System.Xml.XmlException: Reference to undeclared entity 'MyStorageLocation'. Line 183, position 19.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.HandleGeneralEntityReference(String name, Boolean isInAttributeValue, Boolean pushFakeEntityIfNullResolver, Int32 entityStartLinePos)
at System.Xml.XmlTextReaderImpl.ResolveEntity()
at System.Xml.XmlTextReader.ResolveEntity()
at System.Xml.XmlLoader.LoadEntityReferenceNode(Boolean direct)
at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Configuration.ErrorInfoXmlDocument.LoadFromConfigXmlReader(ConfigXmlReader reader)
at System.Configuration.RuntimeConfigurationRecord.RuntimeConfigurationFactory.CreateSectionImpl(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader)
at System.Configuration.RuntimeConfigurationRecord.RuntimeConfigurationFactory.CreateSectionWithRestrictedPermissions(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader)
at System.Configuration.RuntimeConfigurationRecord.CreateSection(Boolean inputIsTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader)
at System.Configuration.BaseConfigurationRecord.CallCreateSection(Boolean inputIsTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader, String filename, Int32 line)
--- End of inner exception stack trace ---
at System.Configuration.BaseConfigurationRecord.EvaluateOne(String[] keys, SectionInput input, Boolean isTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult)
at System.Configuration.BaseConfigurationRecord.Evaluate(FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult, Boolean getLkg, Boolean getRuntimeObject, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSection(String configKey, Boolean getLkg, Boolean checkPermission)
at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at MyCustomWindowsService.Monitor() in D:\...\MyCustomWindowsService.cs:line 207
at MyCustomWindowsService.Start() in D:\...\MyCustomWindowsService.cs:line 178
在配置管理器的内部深处…