1

GitHub에서 찾은 사용자 정의 SettingsProvider를 사용하여 XML 형식의 사용자 정의 클래스를 저장하려고합니다 (죄송하지만 링크를 찾을 수 없습니다). 그러나 출력에는 특수 문자 (예 : <)가 변환됩니다 (아래 참조). 다음과 같이 내가 저장하려고 해요 클래스는 다음과 같습니다목록을 포함하는 클래스에 설정 저장 <CustomClass>

설정 디자이너에서 다음과 같이 설정이 구성되어
[Serializable] 
public class SoundClips 
{ 

    //[System.Xml.Serialization.XmlElementAttribute("Items")] 
    public List<SoundKeyBind> Items { get; set; } 

    public SoundClips() 
    { 
     Items = new List<SoundKeyBind>(); 
    } 

} 

[Serializable] 
public class SoundKeyBind 
{ 
    //[System.Xml.Serialization.XmlElementAttribute("FilePath")] 
    public string FilePath { get; set; } 
    //[System.Xml.Serialization.XmlElementAttribute("FileName")] 
    public string FileName { get; set; } 
    //[System.Xml.Serialization.XmlElementAttribute("Volume")] 
    public float Volume { get; set; } 
    //[System.Xml.Serialization.XmlElementAttribute("KeyBindText")] 
    public string KeyBindText { get; set; } 
    //[System.Xml.Serialization.XmlElementAttribute("KeyBind")] 
    public KeyPressedEventArgs KeyBind { get; set; } 

    public SoundKeyBind (string FilePath, string FileName, float Volume, string KeyBindText, KeyPressedEventArgs KeyBind) 
    { 
     this.FilePath = FilePath; 
     this.FileName = FileName; 
     this.Volume = Volume; 
     this.KeyBindText = KeyBindText; 
     this.KeyBind = KeyBind; 
    } 

    public SoundKeyBind() { } //Required for serialization to work 
} 

[Serializable] 
public class KeyPressedEventArgs : EventArgs 
{ 
    //[System.Xml.Serialization.XmlElementAttribute("Modifier")] 
    public uint Modifier { get; set; } 
    //[System.Xml.Serialization.XmlElementAttribute("Keys")] 
    public Keys Key { get; set; } 

    public KeyPressedEventArgs(uint modifier, Keys key) 
    { 
     this.Modifier = modifier; 
     this.Key = key; 
    } 

    public KeyPressedEventArgs() { } //Required for serialization to work 

} 

:

Name = "SoundBinds" 
Provider = "MySettingsProvider" 
Roaming = "True" 
Scope = "User" 
SettingTypeName="Sound_Board.SoundClips" 

이 같은 값을 절약 해요 :

class SharedVars 
{ 
    //Excess code removed 

    public static SoundClips keyBinds = new SoundClips(); //Stores key bind and sound file info 

} 

//Then elsewhere in the form 
SharedVars.keyBinds.Items.Add(new SoundKeyBind("D:\\Sounds\\Example.mp3", "Example.mp3", 0.5f, "Shift + A", new KeyPressedEventArgs(4, Keys.A))); //Add an example key bind 
Properties.Settings.Default.SoundBinds = SharedVars.keyBinds; 
Properties.Settings.Default.Save(); 

namespace Sound_Board 
{ 
    public sealed class MySettingsProvider : SettingsProvider, IApplicationSettingsProvider 
    { 
     private const string _rootNodeName = "settings"; 
     private const string _localSettingsNodeName = "localSettings"; 
     private const string _globalSettingsNodeName = "globalSettings"; 
     private const string _className = "MySettingsProvider"; 
     private XmlDocument _xmlDocument; 

     private string _filePath 
     { 
      get 
      { 
       return Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), 
        string.Format("{0}.settings", ApplicationName)); 
      } 
     } 

     private XmlNode _localSettingsNode 
     { 
      get 
      { 
       XmlNode settingsNode = GetSettingsNode(_localSettingsNodeName); 
       XmlNode machineNode = settingsNode.SelectSingleNode(Environment.MachineName.ToLowerInvariant()); 

       if (machineNode == null) 
       { 
        machineNode = _rootDocument.CreateElement(Environment.MachineName.ToLowerInvariant()); 
        settingsNode.AppendChild(machineNode); 
       } 

       return machineNode; 
      } 
     } 

     private XmlNode _globalSettingsNode 
     { 
      get { return GetSettingsNode(_globalSettingsNodeName); } 
     } 

     private XmlNode _rootNode 
     { 
      get { return _rootDocument.SelectSingleNode(_rootNodeName); } 
     } 

     private XmlDocument _rootDocument 
     { 
      get 
      { 
       if (_xmlDocument == null) 
       { 
        try 
        { 
         _xmlDocument = new XmlDocument(); 
         _xmlDocument.Load(_filePath); 
        } 
        catch (Exception) 
        { 

        } 

        if (_xmlDocument.SelectSingleNode(_rootNodeName) != null) 
         return _xmlDocument; 

        _xmlDocument = GetBlankXmlDocument(); 
       } 

       return _xmlDocument; 
      } 
     } 

     public override string ApplicationName 
     { 
      get { return Path.GetFileNameWithoutExtension(Application.ExecutablePath); } 
      set { } 
     } 

     public override string Name 
     { 
      get { return _className; } 
     } 

     public override void Initialize(string name, NameValueCollection config) 
     { 
      base.Initialize(Name, config); 
     } 

     public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection) 
     { 
      foreach (SettingsPropertyValue propertyValue in collection) 
       SetValue(propertyValue); 

      try 
      { 
       _rootDocument.Save(_filePath); 
      } 
      catch (Exception) 
      { 
       /* 
       * If this is a portable application and the device has been 
       * removed then this will fail, so don't do anything. It's 
       * probably better for the application to stop saving settings 
       * rather than just crashing outright. Probably. 
       */ 
      } 
     } 

     public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection) 
     { 
      SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); 

      foreach (SettingsProperty property in collection) 
      { 
       values.Add(new SettingsPropertyValue(property) 
       { 
        SerializedValue = GetValue(property) 
       }); 
      } 

      return values; 
     } 

     private void SetValue(SettingsPropertyValue propertyValue) 
     { 
      XmlNode targetNode = IsGlobal(propertyValue.Property) 
       ? _globalSettingsNode 
       : _localSettingsNode; 

      XmlNode settingNode = targetNode.SelectSingleNode(string.Format("setting[@name='{0}']", propertyValue.Name)); 

      if (settingNode != null) 
       settingNode.InnerText = propertyValue.SerializedValue.ToString(); 
      else 
      { 
       settingNode = _rootDocument.CreateElement("setting"); 

       XmlAttribute nameAttribute = _rootDocument.CreateAttribute("name"); 
       nameAttribute.Value = propertyValue.Name; 

       settingNode.Attributes.Append(nameAttribute); 
       settingNode.InnerText = propertyValue.SerializedValue.ToString(); 

       targetNode.AppendChild(settingNode); 
      } 
     } 

     private string GetValue(SettingsProperty property) 
     { 
      XmlNode targetNode = IsGlobal(property) ? _globalSettingsNode : _localSettingsNode; 
      XmlNode settingNode = targetNode.SelectSingleNode(string.Format("setting[@name='{0}']", property.Name)); 

      if (settingNode == null) 
       return property.DefaultValue != null ? property.DefaultValue.ToString() : string.Empty; 

      return settingNode.InnerText; 
     } 

     private bool IsGlobal(SettingsProperty property) 
     { 
      foreach (DictionaryEntry attribute in property.Attributes) 
      { 
       if ((Attribute)attribute.Value is SettingsManageabilityAttribute) 
        return true; 
      } 

      return false; 
     } 

     private XmlNode GetSettingsNode(string name) 
     { 
      XmlNode settingsNode = _rootNode.SelectSingleNode(name); 

      if (settingsNode == null) 
      { 
       settingsNode = _rootDocument.CreateElement(name); 
       _rootNode.AppendChild(settingsNode); 
      } 

      return settingsNode; 
     } 

     public XmlDocument GetBlankXmlDocument() 
     { 
      XmlDocument blankXmlDocument = new XmlDocument(); 
      blankXmlDocument.AppendChild(blankXmlDocument.CreateXmlDeclaration("1.0", "utf-8", string.Empty)); 
      blankXmlDocument.AppendChild(blankXmlDocument.CreateElement(_rootNodeName)); 

      return blankXmlDocument; 
     } 

     public void Reset(SettingsContext context) 
     { 
      _localSettingsNode.RemoveAll(); 
      _globalSettingsNode.RemoveAll(); 

      _xmlDocument.Save(_filePath); 
     } 

     public SettingsPropertyValue GetPreviousVersion(SettingsContext context, SettingsProperty property) 
     { 
      // do nothing 
      return new SettingsPropertyValue(property); 
     } 

     public void Upgrade(SettingsContext context, SettingsPropertyCollection properties) 
     { 
     } 
    } 
} 
: 여기

사용자 정의 SettingsProvider입니다

클래스의 List에는 '안전한'형식으로 변환 된 특수 문자가 있습니다. 나는. <&lt;이되고 두 번째 xml 헤더가 포함되어 있지만 그 이유는 알 수 없습니다. 다음은 설정 파일의 예 출력을 생성하는 중입니다

<?xml version="1.0" encoding="utf-8"?> 
<settings> 
    <globalSettings> 
    <setting name="SecondaryOutputDeviceID">-1</setting> 
    <setting name="InjectMicOutputDeviceID">1</setting> 
    <setting name="InjectMicInputDeviceID">0</setting> 
    <setting name="PrimaryOutputDeviceID">-1</setting> 
    <setting name="InjectMicEnabled">False</setting> 
    <setting name="SoundBinds">&lt;?xml version="1.0" encoding="utf-16"?&gt; 
&lt;SoundClips xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt; 
    &lt;Items&gt; 
    &lt;SoundKeyBind&gt; 
     &lt;FilePath&gt;D:\Sounds\Example.mp3&lt;/FilePath&gt; 
     &lt;FileName&gt;Example.mp3&lt;/FileName&gt; 
     &lt;Volume&gt;0.5&lt;/Volume&gt; 
     &lt;KeyBindText&gt;Shift + A&lt;/KeyBindText&gt; 
     &lt;KeyBind&gt; 
     &lt;Modifier&gt;4&lt;/Modifier&gt; 
     &lt;Key&gt;A&lt;/Key&gt; 
     &lt;/KeyBind&gt; 
    &lt;/SoundKeyBind&gt; 
    &lt;/Items&gt; 
&lt;/SoundClips&gt;</setting> 
    </globalSettings> 
</settings> 

답변

2

특수 문자 이스케이프되고 당신이 innerText와 대신 InnerXml을 설정하고 있기 때문이다.

두 개의 차이점을 보여주는 예는 다음과 같습니다. in MSDN.

+0

감사합니다. 나는 InnerXml이 존재한다는 것을 몰랐다. "SoundBinds"노드 안에 여전히 두 번째 헤더를 만드는 이유는 무엇입니까? – Daniel

+0

@ 대니얼, 나는 완전히 확신하지 못합니다. 'SettingsPropertyValue.SerializedValue'가 어떻게 작동하는지와 관련이 있어야합니다. 시도 할 수있는 것들 : -'targetNode.InnerXml'을 빈 문자열로 설정하고,'SerializedValue.ToString()'의'LoadXml()'을'targetNode.AppendChild()'에 전달하십시오; - SerializedValue 속성은 아마도 XmlNode로, 문자열로 변환 한 다음 XML을로드하는 대신 XmlNode로 캐스팅을 시도 할 수 있습니다. - 위 옵션을 사용해도 도움이되지 않는 경우 로직을 추가하여 을 직접 삭제해야 할 수 있습니다. –

관련 문제