2017-12-28 13 views
1

Ich versuche, die folgenden Klassen mit einem benutzerdefinierten Settings Provider zu speichern, aber immer einen Null Referenzfehler (Fehlerdetails unten) erhalten.Serialisierung von benutzerdefinierten Klassen mit benutzerdefinierten Einstellungen Provider

[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 
{ 
    public string FilePath { get; set; } 
    public string FileName { get; set; } 
    public string KeyBindText { get; set; } 
    public KeyPressedEventArgs KeyBind { get; set; } 
} 

Saved by:

 dgvSoundBoard.DataSource = keyBinds.Items; 
     Properties.Settings.Default.SoundBinds = keyBinds; 
     Properties.Settings.Default.Save(); 

habe ich den Provider folgende Einstellungen auf GitHub irgendwo aber den Link es verweisen nicht finden können, sorry.

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); 

      // ######### ERROR OCCURS HERE ######### 
      settingNode.InnerText = propertyValue.SerializedValue.ToString(); 
      // ######### ERROR OCCURS HERE ######### 

      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) 
    { 
    } 
} 

Der Fehler tritt in der Provider-Einstellungen, in private void SetValue(SettingsPropertyValue propertyValue), wenn er versucht propertyValue.SerializedValue.ToString() zuzugreifen, die null ist. Ich habe es im obigen Code kommentiert, um den Standort hervorzuheben. Der Fehler ist:

An unhandled exception of type 'System.NullReferenceException' occurred in SoundBoard.exe Object reference not set to an instance of an object.

Im Einstellungen Designer ich den Provider der Einstellung MySettingsProvider eingestellt haben und Festlegen von Roaming auf True. Ich vermute, dass ich etwas falsch mit der Serialisierung Erklärung für die Klassen habe, aber ich habe ein paar Dinge ausprobiert, zum Beispiel:

[Serializable] 
[SettingsSerializeAs(SettingsSerializeAs.Xml)] 
public class SoundClips 

und kann es nicht herausgefunden.

Jede Hilfe würde sehr geschätzt werden.

Antwort

0

Ich schaffte es, das Problem zu lösen, indem ich die Klasse durchbrach und jedes Bit einzeln speicherte. Das Problem stellte sich heraus, dass die SoundKeyBind Klasse und die KeyPressedEventArgs Klasse/Objekt, die darin erstellt wurde, einen Konstruktor benötigte, der keine Parameter akzeptiert.

I.e. Ich brauchte die folgenden zu den jeweiligen Klassen hinzuzufügen:

public SoundKeyBind() { } 

und

public KeyPressedEventArgs() { } 
Verwandte Themen