是否可以在自定义配置部分中使用任意XML?

时间:2009-02-03 23:26:19

标签: .net asp.net

假设我在ASP.NET web.config中定义了一个配置部分,如:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <sectionGroup name="system.web">
      <section name="MySettings" type="MyCompany.MyProject.Configuration.MySettings" allowLocation="true" allowDefinition="Everywhere" restartOnExternalChanges="false" />
    </sectionGroup>
  </configSections>
  <system.web>
    <MySettings knownProperty="some_value" unknownProperty="other_value" />
  </system.web>
</configuration>

假设我在没有 MySettings : System.Configuration.ConfigurationSection的情况下定义unknownProperty

using System.Configuration;

namespace MyCompany.MyProject.Configuration
{
    public class MySettings : ConfigurationSection
    {
      public MySettings() { }

      [ConfigurationProperty("knownProperty", DefaultValue="default_value")]
      public string KnownProperty
      {
        get { return (string)this["knownProperty"]; }
      }

      // I'm not defining unknownProperty here on purpose
    }
}

是否有运行应用程序而没有收到配置错误抱怨无法识别的属性'unknownProperty'?

此外,我可以通过一种方法来捕捉该错误并在可能的情况下忽略它。

换句话说,我希望XML具有一个未在其绑定的匹配类型中定义的属性。可以在现有Configuration API的范围内完成吗?

4 个答案:

答案 0 :(得分:7)

我很确定这是可能的,因为一些内置的部分,如WCF和成员资格,这样做没有错误。 OnDeserializeUnrecognizedAttribute是否满足您的需求?

protected override bool OnDeserializeUnrecognizedAttribute(string name, string value){
//don't call base to avoid error
}

答案 1 :(得分:2)

我正在使用下面的代码从我的web.config ASP文件中成功读取任何XML结构。请注意,仅支持阅读。

using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Xml;

/* In this file, you'll find an example on how to store an custom section in an .Net 
 * application configuration file that can contains arbitrary XML that can be retrieved 
 * as a raw System.Xml.XmlNode. In the specific example below, I wanted to be able to 
 * store arbitrary information about POP servers I retrieve email from, without having to 
 * write specific Configuration data for each different case. This is usefull for quick
 * application development.
 */

/* Config file sample : 
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="MySection">
            <section name="MailRetrieve" type="ConsoleApplication1.MailRetrieveConfigurationSection, ConsoleApplication1"/>
        </sectionGroup>
    </configSections>


    <MySection>
        <MailRetrieve>
            <Hosts>
                <add username="projects@domain.com" popserver="mail.domain.com" password="1234">
                    <RawXml>
                        <AnElement>Arbitrary string one</AnElement>
                    </RawXml>
                </add>
                <add username="tasks@domain.com" popserver="mail.domain.com" password="1234"></add>
                <add username="bugs@domain.com" popserver="mail.domain.com" password="1234" >
                    <RawXml>
                        <OtherElement>Arbitrary string two</OtherElement>
                    </RawXml>
                </add>
            </Hosts>
        </MailRetrieve>
    </MySection>
  </configuration>
 */

/* Sample output : running the piece of code below, using config file above, gives :

        Custom XML for projects@domain.com__@__mail.domain.com:
        <RawXml><AnElement>Arbitrary string one</AnElement></RawXml>
        ************
        Custom XML for tasks@domain.com__@__mail.domain.com:
         - none -
        ************
        Custom XML for bugs@domain.com__@__mail.domain.com:
        <RawXml><OtherElement>Arbitrary string two</OtherElement></RawXml>
        --> Found OtherElement !
        ************
        Hit a key to finish

 */

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {

            MailRetrieveConfigurationSection config = (MailRetrieveConfigurationSection)
                    (System.Configuration.ConfigurationManager.GetSection("MySection/MailRetrieve"));


            if (config != null) {
                foreach (HostConfigElement cfg in config.Hosts) {
                    System.Console.WriteLine("Custom XML for " + cfg.PopMailboxID + ":");
                    if (cfg.RawXml.Node != null) {
                        System.Console.WriteLine(cfg.RawXml.Node.OuterXml);
                        if (cfg.RawXml.Node.SelectSingleNode("OtherElement") != null) {
                            Console.WriteLine("--> Found OtherElement !");
                        }
                    }
                    else {
                        System.Console.WriteLine(" - none -");
                    }
                    System.Console.WriteLine("************");                    
                }
            }
            System.Console.WriteLine("Hit a key to finish");
            System.Console.ReadKey();
        }
    }


    public class MailRetrieveConfigurationSection : ConfigurationSection {
        [ConfigurationProperty("Hosts")]
        public MailRetrieveHostsConfigCollection Hosts {
            get {
                return ((MailRetrieveHostsConfigCollection)(base["Hosts"]));
            }
        }
    }

    [ConfigurationCollectionAttribute(typeof(HostConfigElement))]
    public class MailRetrieveHostsConfigCollection : ConfigurationElementCollection {
        protected override ConfigurationElement CreateNewElement() {
            return new HostConfigElement();
        }

        /// <summary>
        /// We want to have only one configuration per POP mailbox, wich key is host+username
        /// If more configuration is wanted, one must introduce an "id" attribute.
        /// </summary>        
        protected override object GetElementKey(ConfigurationElement element) {
            return ((HostConfigElement)(element)).PopMailboxID;
        }

        public void Add(HostConfigElement element) {
            this.BaseAdd(element);
        }

        public void Remove(string key) {
            this.BaseRemove(key);
        }

        public void Clear() {
            this.BaseClear();
        }


        public HostConfigElement this[int idx] {
            get { return (HostConfigElement)this[idx]; }
        }
    }


    public class MyCustomConfigurationElement : ConfigurationElement {

        public XmlNode Node = null;

        protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey) {                       
            XmlDocument doc = new XmlDocument();
            doc.Load(reader.ReadSubtree());
            Node = doc.FirstChild;
        }        
    }

    public class HostConfigElement : ConfigurationElement {

        /// <summary>
        /// A POP3 mailbox is distinguished from another using the server name and user name.
        /// </summary>
        public string PopMailboxID {
            get {
                return Username + "__@__" + PopServer; //
            }
        }


        [ConfigurationProperty("popserver", DefaultValue = "", IsRequired = true)]
        public string PopServer {
            get { return (string)this["popserver"]; }
            set { this["popserver"] = value; }
        }

        [ConfigurationProperty("username", IsRequired = true, Options = ConfigurationPropertyOptions.IsKey)]
        public string Username {
            get { return (string)this["username"]; }
            set { this["username"] = value; }
        }

        [ConfigurationProperty("password", DefaultValue = "", IsRequired = true)]
        public string Password {
            get { return (string)this["password"]; }
            set { this["password"] = value; }
        }


        [ConfigurationProperty("RawXml", IsRequired=false)]
        public MyCustomConfigurationElement RawXml {
            get { return (MyCustomConfigurationElement)this["RawXml"]; }
            set { this["RawXml"] = value; }
        }


    }
}

答案 2 :(得分:2)

继Daniel的回答后: -

protected override bool OnDeserializeUnrecognizedAttribute(string name, string value) {
    try {
        var lProperty = new ConfigurationProperty(name, typeof(String));
        Properties.Add(lProperty);
        base[name] = value;
        return true;
    } catch {
        return false;
    }
}

答案 3 :(得分:0)

这是我最后得到的最少的代码示例:

auto

在这里获取xml元素

public class XmlConfigurationSection : ConfigurationSection
{
    [ConfigurationProperty("xml", IsRequired = false)]
    public XmlElement Xml
    {
        get { return (XmlElement)this["xml"]; }
        set { this["xml"] = value; }
    }
}

public class XmlElement : ConfigurationElement
{
    public XmlNode Node = null;

    protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(reader.ReadSubtree());
        Node = doc.FirstChild;
    }
}

WebConfig 设置如下:

var xml = (System.Configuration.ConfigurationManager.GetSection("xmlSettings") as XmlConfigurationSection).Xml;