C# 如何从列表迁移到C类#DataContract序列化?
如何将配置从布尔列表迁移到新类?以前它使用bool列表,但该列表作为一个类被滥用,每个索引都有一个特定的含义,比如一个字段 我想将它从一个列表迁移到一个类,该类在序列化时充当列表,但向应用程序的其余部分公开普通字段 如何编写类ListMulator,使其序列化为列表,而不引入新的xml标记 旧代码C# 如何从列表迁移到C类#DataContract序列化?,c#,serialization,datacontractserializer,C#,Serialization,Datacontractserializer,如何将配置从布尔列表迁移到新类?以前它使用bool列表,但该列表作为一个类被滥用,每个索引都有一个特定的含义,比如一个字段 我想将它从一个列表迁移到一个类,该类在序列化时充当列表,但向应用程序的其余部分公开普通字段 如何编写类ListMulator,使其序列化为列表,而不引入新的xml标记 旧代码 namespace { [DataContract] public class Configuration { public const string File
namespace
{
[DataContract]
public class Configuration
{
public const string FileName = "Configuration.xml";
public Configuration()
{
AList = new List<bool>();
AGuidList = new List<Guid>();
}
[DataMember]
public List<Guid> AGuidList { get; set; }
[DataMember]
public List<bool> AList { get; set; }
}
}
名称空间
{
[数据合同]
公共类配置
{
public const string FileName=“Configuration.xml”;
公共配置()
{
AList=新列表();
AGuidList=新列表();
}
[数据成员]
公共列表列表{get;set;}
[数据成员]
公共列表列表{get;set;}
}
}
新代码
namespace
{
[DataContract]
public class Configuration
{
public const string FileName = "Configuration.xml";
public Configuration()
{
AListEmulator = new ListEmulator();
AGuidList = new List<Guid>();
}
[DataMember]
public List<Guid> AGuidList { get; set; }
[DataMember]
public ListEmulator AListEmulator { get; set; }
}
}
public class ListEmulator
{
public ListEmulator()
{
new ListEmulator(true, true, true, true);
}
public ListEmulator(bool item0, bool item1, bool item2, bool item3)
{
this.IsPlanned = item0;
this.IsCompleted = item1;
this.IsRemaining = item2;
this.IsSerial = item3;
}
public bool IsPlanned { get; set; }
public bool IsCompleted { get; set; }
public bool IsRemaining { get; set; }
public bool IsSerial { get; set; }
}
名称空间
{
[数据合同]
公共类配置
{
public const string FileName=“Configuration.xml”;
公共配置()
{
AListEmulator=新建ListSimulator();
AGuidList=新列表();
}
[数据成员]
公共列表列表{get;set;}
[数据成员]
公共ListSimulator{get;set;}
}
}
公共类监听器
{
公共ListSimulator()
{
新ListSimulator(真,真,真,真);
}
公共ListSimulator(布尔项0、布尔项1、布尔项2、布尔项3)
{
this.IsPlanned=item0;
this.IsCompleted=第1项;
this.IsRemaining=item2;
此.IsSerial=第3项;
}
公共布尔值已规划{get;set;}
公共布尔已完成{get;set;}
公共bool正在生成{get;set;}
公共布尔值序列{get;set;}
}
需要列表的原因是,当只有1个元素,然后是2、3、4个元素时,需要移植旧的迁移代码,每个元素都有不同的默认值。如果不是因为我已经以原始格式部署了现有的配置文件,那么可能是时候用XML分别命名它们了。但是,我现在需要保留当前的格式。为了迁移,我想知道如何才能完成上述操作。一个选项是让您的
ListMulator继承,然后添加特定的命名属性来访问数组中的元素,如下所示:
public class ListEmulator : Collection<bool>
{
const bool IsPlannedDefault = false; // Change to the appropriate values.
const bool IsCompletedDefault = false;
const bool IsRemainingDefault = false;
const bool IsSerialDefault = false;
void AddAllDefaults()
{
// Customize the code here to upgrade old collections with fewer than 4 elements to the current 4-element format.
if (Count < 1)
Add(IsPlannedDefault);
if (Count < 2)
Add(IsCompletedDefault);
if (Count < 3)
Add(IsRemainingDefault);
if (Count < 4)
Add(IsSerialDefault);
}
public ListEmulator() { }
public ListEmulator(bool item0, bool item1, bool item2, bool item3)
{
this.IsPlanned = item0;
this.IsCompleted = item1;
this.IsRemaining = item2;
this.IsSerial = item3;
}
public bool IsPlanned { get { return this.ElementAtOrDefault(0, IsPlannedDefault); } set { AddAllDefaults(); this[0] = value; } }
public bool IsCompleted { get { return this.ElementAtOrDefault(1, IsCompletedDefault); } set { AddAllDefaults(); this[1] = value; } }
public bool IsRemaining { get { return this.ElementAtOrDefault(2, IsRemainingDefault); } set { AddAllDefaults(); this[2] = value; } }
public bool IsSerial { get { return this.ElementAtOrDefault(3, IsSerialDefault); } set { AddAllDefaults(); this[3] = value; } }
protected override void InsertItem(int index, bool item)
{
if (index > 3)
throw new ArgumentOutOfRangeException("index > 3");
base.InsertItem(index, item);
}
}
由于此类型实现了IEnumerable
,因此DataContractSerializer
将其序列化为集合,而不是具有属性的对象。(您可能需要更改类名,因为此时它实际上不是列表仿真器。)但是,只有在不从默认构造函数向集合添加任何初始值的情况下,这才有效
另一个选项是将代理属性添加到处理必要转换的配置
,并将ListMulator列表
标记为未序列化:
[DataContract]
public class Configuration
{
public const string FileName = "Configuration.xml";
public Configuration()
{
AList = new ListEmulator();
AGuidList = new List<Guid>();
}
[DataMember]
public List<Guid> AGuidList { get; set; }
[DataMember(Name = "AList")]
bool[] AlistArray
{
get
{
return AList == null ? null : AList.ToArray();
}
set
{
AList = new ListEmulator(value);
}
}
[IgnoreDataMember] // Do not serialize this property directly
public ListEmulator AList { get; set; }
}
public class ListEmulator
{
const bool IsPlannedDefault = false; // Change to the appropriate values.
const bool IsCompletedDefault = false;
const bool IsRemainingDefault = false;
const bool IsSerialDefault = false;
public ListEmulator(IList<bool> list)
{
IsPlanned = list.ElementAtOrDefault(0, IsPlannedDefault);
IsCompleted = list.ElementAtOrDefault(1, IsCompletedDefault);
IsRemaining = list.ElementAtOrDefault(2, IsRemainingDefault);
IsSerial = list.ElementAtOrDefault(3, IsSerialDefault);
}
public ListEmulator()
{
new ListEmulator(true, true, true, true);
}
public ListEmulator(bool item0, bool item1, bool item2, bool item3)
{
this.IsPlanned = item0;
this.IsCompleted = item1;
this.IsRemaining = item2;
this.IsSerial = item3;
}
public bool IsPlanned { get; set; }
public bool IsCompleted { get; set; }
public bool IsRemaining { get; set; }
public bool IsSerial { get; set; }
public bool[] ToArray()
{
return new[] { IsPlanned, IsCompleted, IsRemaining, IsSerial };
}
}
[DataContract]
公共类配置
{
public const string FileName=“Configuration.xml”;
公共配置()
{
AList=新的ListSimulator();
AGuidList=新列表();
}
[数据成员]
公共列表列表{get;set;}
[DataMember(Name=“AList”)]
布尔数组
{
得到
{
返回AList==null?null:AList.ToArray();
}
设置
{
AList=新的ListSimulator(值);
}
}
[IgnoreDataMember]//不要直接序列化此属性
公共ListEmulator AList{get;set;}
}
公共类监听器
{
const bool isplannedefault=false;//更改为适当的值。
const bool iscompletedefault=false;
const bool IsRemainingDefault=false;
const bool IsSerialDefault=假;
公共ListSimulator(IList列表)
{
IsPlanned=list.ElementAtOrDefault(0,isplannededefault);
IsCompleted=list.ElementAtOrDefault(1,iscompletededefault);
IsRemaining=list.ElementAtOrDefault(2,IsRemainingDefault);
IsSerial=list.ElementAtOrDefault(3,IsSerialDefault);
}
公共ListSimulator()
{
新ListSimulator(真,真,真,真);
}
公共ListSimulator(布尔项0、布尔项1、布尔项2、布尔项3)
{
this.IsPlanned=item0;
this.IsCompleted=第1项;
this.IsRemaining=item2;
此.IsSerial=第3项;
}
公共布尔值已规划{get;set;}
公共布尔已完成{get;set;}
公共bool正在生成{get;set;}
公共布尔值序列{get;set;}
公共图书馆[]ToArray()
{
返回新[]{IsPlanned,IsCompleted,IsRemaining,IsSerial};
}
}
两个选项都使用以下扩展方法:
public static class ListExtensions
{
public static T ElementAtOrDefault<T>(this IList<T> list, int index, T defaultValue)
{
if (index < 0)
throw new ArgumentOutOfRangeException(string.Format("index = {0}", index));
if (list == null || index >= list.Count)
return defaultValue;
return list[index];
}
}
公共静态类ListExtensions
{
公共静态T ElementAtOrDefault(此IList列表,int索引,T defaultValue)
{
如果(指数<0)
抛出新ArgumentOutOfRangeException(string.Format(“index={0}”,index));
if(list==null | | index>=list.Count)
返回默认值;
返回列表[索引];
}
}
您的意思是,您希望您的XML继续具有bool
值的数组,还是希望您的XML更改为实际显示有意义的元素名称,如true
,并在读取时正确升级?在您编写的问题的开头,您希望在不引入新的xml标记的情况下实现这一点,但在后面编写的问题中,可能是时候在xml中分别命名它们了。你想要哪一个?第一个。主要是出于教育原因。知道如何读第一个,但写第二个,以及读第二个会很好。事实上,第二个在我看来更容易,但我会看看我是否能回答这个问题
public static class ListExtensions
{
public static T ElementAtOrDefault<T>(this IList<T> list, int index, T defaultValue)
{
if (index < 0)
throw new ArgumentOutOfRangeException(string.Format("index = {0}", index));
if (list == null || index >= list.Count)
return defaultValue;
return list[index];
}
}