[英]Best way to serialize and deserialize XML in C# so as to reuse the XML file, model class, and UserControl
我有一個XML文件,其中包含最終將在兩個UserControl中顯示的數據。 大多數數據是通用的,而某些是特定於所涉及的UserControl的。 我想成為一個好公民,並盡可能地重用代碼。 要給出一個具體示例(大大簡化),請考慮以下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>
最終,我想在兩個UserControl上顯示此信息,一個用於家庭廚房,一個用於餐廳。 在這兩個控件上,我只想顯示
名稱:可見:
顯然,在“家用廚房”控件上,我想顯示“ VisibleAtHome”,在餐廳上顯示“ VisibleAtRestaurant”。 可能,我做事的方式是最好的。 但是請注意,我必須擁有兩個幾乎完全相同的控件。 在一個控件上,我需要綁定到VisibleAtHome,並在另一個上綁定到VisibleAtRestaurant。 擁有一個控件會很好。
我可以想到一些可能的改進。
也許可以只使用1個控件並在運行時更改綁定。 這是有好處的,但是鑒於有問題的屬性位於可能反過來位於集合中的集合內部,因此我認為可能很難做到(記住,我正在提供一個簡化的示例)。
也許在我的模型類中,我可以只擁有“ Visible”屬性,並根據需要在VisibleAtHome或VisibleAtRestaurant中讀取。 請參見我可以在運行時將屬性添加到對象屬性嗎? 有關如何完成此操作的信息,但是請注意,我當前的處理方式是,將整個文件讀入模型,然后將整個模型保存回文件。 我不想因為我正在使用VisibleAtHome而丟失有關VisibleAtRestaurant的信息。
我可以有一個不可序列化的屬性“ Visible”,它根據傳遞給構造函數的內容返回VisibleAtHome或VisibleAtRestaurant。 不確定這樣做是否可行,因為在序列化/反序列化時需要無參數的構造函數(對嗎?)。 另外,Model類必須以某種方式告訴Widget類正在發生的事情。
有人對此有任何想法嗎? 同樣,我的目標是僅擁有(a)一個XML文件(實際上,這是必須的!),(b)一個模型類和(c)一個UserControl。 (d)我不想在任何地方都鍵入VisibleAtRestaurant和VisibleAtHome。 那是維護的噩夢。 我做了a)和b)。 現在我只需要c)和d)的幫助。 之所以出現這個問題,是因為我從一個僅需要在1個用戶控件中顯示的模型開始,並且(您猜到了),有人(老板)決定我們需要在大多數情況下都需要顯示該模型的情況下顯示模型。相同,但某些屬性可能具有不同的值,具體取決於您在哪里顯示模型。 我的“廚房”與“餐館”的想法是我試圖簡化和隱藏專有信息。
謝謝戴夫
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);
}
}
}
對家庭使用一個模型類,對餐廳使用另一個模型類,並擺脫VisibleAt這個元素。 假設您應該添加另一個實體,例如食品博覽會,則只需為其創建另一個模型類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.