无法序列化类型为Enum的DataTable.DefaultColumn

时间:2014-11-11 20:13:40

标签: c# xml enums dataset

我正在尝试将DataSet序列化为XML,并在作为Enum的列上提供默认值。似乎.NET无法将序列化值(int)强制转换为枚举值。

是否可以通过序列化程序将DataColumn.DefaultValue分配给枚举?目前我已经实现了一种解决方法,其中在XML的使用者上手动分配了DefaultValue。

以下是失败的示例代码。

public enum Foo
{
    Bar = 0
}

class Program
{
    static void Main(string[] args)
    {
        using (MemoryStream stream = new MemoryStream())
        {
            using (DataSet dataSet = new DataSet())
            using (DataTable table = new DataTable())
            {
                dataSet.Tables.Add(table);

                DataColumn column = table.Columns.Add("Foo", typeof(Foo));
                column.DefaultValue = Foo.Bar;

                dataSet.WriteXml(stream, XmlWriteMode.WriteSchema);
            }

            stream.Seek(0, SeekOrigin.Begin);

            using (DataSet dataSet = new DataSet())
            {
                dataSet.ReadXml(stream);

                DataTable table = dataSet.Tables[0];
                DataColumn column = table.Columns["Foo"];
                Console.WriteLine(column.DefaultValue.GetType());
            }
        }
    }
}

以下是由于DataSet.ReadXml方法调用而产生的异常。

Unhandled Exception: System.ArgumentException: The DefaultValue for column Foo is of type System.Int32, but the column is of type ConsoleApplication80.Foo. --->
 System.InvalidCastException: Invalid cast from 'System.Int32' to 'ConsoleApplication80.Foo'.
   at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
   at System.Int32.System.IConvertible.ToType(Type type, IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at System.Data.Common.SqlConvert.ChangeType2(Object value, StorageType stype, Type type, IFormatProvider formatProvider)
   at System.Data.Common.SqlConvert.ChangeTypeForDefaultValue(Object value, Type type, IFormatProvider formatProvider)
   at System.Data.DataColumn.set_DefaultValue(Object value)
   --- End of inner exception stack trace ---
   at System.Data.DataColumn.set_DefaultValue(Object value)
   at System.Data.XSDSchema.HandleElementColumn(XmlSchemaElement elem, DataTable table, Boolean isBase)
   at System.Data.XSDSchema.HandleParticle(XmlSchemaParticle pt, DataTable table, ArrayList tableChildren, Boolean isBase)
   at System.Data.XSDSchema.HandleComplexType(XmlSchemaComplexType ct, DataTable table, ArrayList tableChildren, Boolean isNillable)
   at System.Data.XSDSchema.InstantiateTable(XmlSchemaElement node, XmlSchemaComplexType typeNode, Boolean isRef)
   at System.Data.XSDSchema.HandleTable(XmlSchemaElement node)
   at System.Data.XSDSchema.HandleDataSet(XmlSchemaElement node, Boolean isNewDataSet)
   at System.Data.XSDSchema.LoadSchema(XmlSchemaSet schemaSet, DataSet ds)
   at System.Data.DataSet.ReadXSDSchema(XmlReader reader, Boolean denyResolving)
   at System.Data.DataSet.ReadXml(XmlReader reader, Boolean denyResolving)
   at System.Data.DataSet.ReadXml(Stream stream)
   at ConsoleApplication80.Program.Main(String[] args) in c:\Users\jonathan.berube\Documents\Visual Studio 2013\Projects\ConsoleApplication80\ConsoleApplication80\Program.cs:line 39

这里还有输出XML:

<NewDataSet>
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="Table1">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="Foo" type="xs:int" default="0" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
</NewDataSet>

1 个答案:

答案 0 :(得分:0)

由于你的枚举值的基础类型是int32,你需要做类似我在下面做的事情。您还可以使表上的列类型为字符串,而默认值为Foo.Bar.ToString()。

using (MemoryStream stream = new MemoryStream())
        {
            using (DataSet dataSet = new DataSet())
            {
                using (DataTable table = new DataTable("Mytable"))
                {

                    dataSet.Tables.Add(table);

                    DataColumn column = table.Columns.Add("Foo", Enum.GetUnderlyingType(typeof(Foo)));
                    column.DefaultValue= Foo.Bar;
                   dataSet.WriteXml(stream, XmlWriteMode.WriteSchema);
                }

                stream.Seek(0, SeekOrigin.Begin);
            }
            using (DataSet dataSet = new DataSet())
            {
                dataSet.ReadXml(stream);

                DataTable table = dataSet.Tables[0];
                DataColumn column = table.Columns["Foo"];
                Console.WriteLine(column.DefaultValue.GetType());
            }