简体   繁体   English

在C#中序列化和反序列化XML以便重用XML文件,模型类和UserControl的最佳方法

[英]Best way to serialize and deserialize XML in C# so as to reuse the XML file, model class, and UserControl

I have an XML File that contains data that will ultimately be shown in two UserControls. 我有一个XML文件,其中包含最终将在两个UserControl中显示的数据。 Most of the data is common, and some is particular to the UserControl in question. 大多数数据是通用的,而某些是特定于所涉及的UserControl的。 I want to be a good citizen and reuse code as much as possible. 我想成为一个好公民,并尽可能地重用代码。 To give a specific example (greatly simplified), consider this XML: 要给出一个具体示例(大大简化),请考虑以下XML:

<?xml version="1.0"?>
<Model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<Widgets>
<Widget>
  <Name>Fork</Name>
  <VisibleAtHome>true</VisibleAtHome>
  <VisibleAtRestaurant>true</VisibleAtRestaurant>
</Widget>
<Widget>
  <Name>ProfessionalMixer</Name>
  <VisibleAtHome>false</VisibleAtHome>
  <VisibleAtRestaurant>true</VisibleAtRestaurant>
</Widget>
</Widgets>
</Model>

Ultimately, I want to show this info on two UserControls, one for the Home Kitchen, and one for a Restaurant. 最终,我想在两个UserControl上显示此信息,一个用于家庭厨房,一个用于餐厅。 On those two controls, I'd like to just show 在这两个控件上,我只想显示

Name: Visible: 名称:可见:

Obviously, on the Home Kitchen control, I'd like to show "VisibleAtHome", and on the Restaurant, "VisibleAtRestaurant". 显然,在“家用厨房”控件上,我想显示“ VisibleAtHome”,在餐厅上显示“ VisibleAtRestaurant”。 Possibly, the way I'm doing things is the best that can be done. 可能,我做事的方式是最好的。 But note that I have to have two controls that are almost identical. 但是请注意,我必须拥有两个几乎完全相同的控件。 On one control, I need to bind to VisibleAtHome and on the other VisibleAtRestaurant. 在一个控件上,我需要绑定到VisibleAtHome,并在另一个上绑定到VisibleAtRestaurant。 It would be nice to just have one control. 拥有一个控件会很好。

I can think of some possible improvements. 我可以想到一些可能的改进。

  1. Perhaps it's possible to use just 1 control and change the bindings at runtime. 也许可以只使用1个控件并在运行时更改绑定。 This has merit, but I think it might be hard to do given that the properties in question are inside of collections that might in turn be in collections (remember, I'm presenting a much simplified example). 这是有好处的,但是鉴于有问题的属性位于可能反过来位于集合中的集合内部,因此我认为可能很难做到(记住,我正在提供一个简化的示例)。

  2. Perhaps in my model class I could have just the property "Visible" and read in VisibleAtHome or VisibleAtRestaurant depending on what I need. 也许在我的模型类中,我可以只拥有“ Visible”属性,并根据需要在VisibleAtHome或VisibleAtRestaurant中读取。 See Can I add attributes to an object property at runtime? 请参见我可以在运行时将属性添加到对象属性吗? for how this might be done, but note that the way I'm currently doing things, I read in the whole file into a model, and then save the whole model back to file. 有关如何完成此操作的信息,但是请注意,我当前的处理方式是,将整个文件读入模型,然后将整个模型保存回文件。 I don't want to lose info on VisibleAtRestaurant just because I'm working on VisibleAtHome. 我不想因为我正在使用VisibleAtHome而丢失有关VisibleAtRestaurant的信息。

  3. I could have a non-serializable property "Visible", that returns VisibleAtHome or VisibleAtRestaurant depending on what is passed into a constructor. 我可以有一个不可序列化的属性“ Visible”,它根据传递给构造函数的内容返回VisibleAtHome或VisibleAtRestaurant。 Not sure this will work though as you need parameterless constructors when you're serializing/deserializing (correct?). 不确定这样做是否可行,因为在序列化/反序列化时需要无参数的构造函数(对吗?)。 Also, Model class would have to somehow tell Widget class about what's going on. 另外,Model类必须以某种方式告诉Widget类正在发生的事情。

Anyone have any ideas on this? 有人对此有任何想法吗? Again, my goal would be to just have (a) one XML file (actually, that's a must!), (b) one model class, and (c) one UserControl. 同样,我的目标是仅拥有(a)一个XML文件(实际上,这是必须的!),(b)一个模型类和(c)一个UserControl。 (d) I'd prefer not to have to type VisibleAtRestaurant and VisibleAtHome everywhere. (d)我不想在任何地方都键入VisibleAtRestaurant和VisibleAtHome。 That's a maintenance nightmare. 那是维护的噩梦。 I have done a) and b). 我做了a)和b)。 Now I just need help on c) and d). 现在我只需要c)和d)的帮助。 This question came about because I started with a Model that just needed to be display in 1 user control, and (you guessed it), someone (boss) decided we needed to show the model in a different situation where most of the properties are the same but some properties might have different values depending on where you are showing the model. 之所以出现这个问题,是因为我从一个仅需要在1个用户控件中显示的模型开始,并且(您猜到了),有人(老板)决定我们需要在大多数情况下都需要显示该模型的情况下显示模型。相同,但某些属性可能具有不同的值,具体取决于您在哪里显示模型。 My "Kitchen" versus "Restaurant" idea was my attempt to both simplify and hide proprietary info. 我的“厨房”与“餐馆”的想法是我试图简化和隐藏专有信息。

Thanks Dave 谢谢戴夫

PS, Here are my model classes: PS,这是我的模型课:

 public class Model :  INotifyPropertyChanged
{
    public Model()
    {

    }
    private List<Widget> _widgets = new List<Widget>();

    [System.Xml.Serialization.XmlArray("Widgets"),
    System.Xml.Serialization.XmlArrayItem(typeof(Widget))]
    public Widget[] Widgets
    {
        get { return _widgets.ToArray(); }
        set
        {
            _widgets = new List<Widget>(value);//value;
            OnPropertyChanged("Widgets");
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    /// <summary>
    /// Raises this object's PropertyChanged event.
    /// </summary>
    /// <param name="propertyName">The property that has a new value.</param>
    protected virtual void OnPropertyChanged(string propertyName)
    {

        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }
}


public class Widget :  INotifyPropertyChanged
{
    private string _name;
    public string Name
    {
        get {
            return _name;
        }
        set 
        {
            if (_name != value)
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
    }

    // many more common properties in real case...

    private string _visibleAtHome;
    public string VisibleAtHome
    {
        get {
            return _visibleAtHome;
        }
        set 
        {
            if (_visibleAtHome != value)
            {
                _visibleAtHome = value;
                OnPropertyChanged("VisibleAtHome");
            }
        }
    }

    private string _visibleAtRestaurant;
    public string VisibleAtRestaurant
    {
        get {
            return _visibleAtRestaurant;
        }
        set 
        {
            if (_visibleAtRestaurant != value)
            {
                _visibleAtRestaurant = value;
                OnPropertyChanged("VisibleAtRestaurant");
            }
        }
    }

     public event PropertyChangedEventHandler PropertyChanged;
    /// <summary>
    /// Raises this object's PropertyChanged event.
    /// </summary>
    /// <param name="propertyName">The property that has a new value.</param>
    protected virtual void OnPropertyChanged(string propertyName)
    {

        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }
}

Use a model class for home and another model class for restaurant and get rid of this elements VisibleAt. 对家庭使用一个模型类,对餐厅使用另一个模型类,并摆脱VisibleAt这个元素。 Suppose you should add another entity like a food expo, you just create another model class for it. 假设您应该添加另一个实体,例如食品博览会,则只需为其创建另一个模型类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM