C# “救救我”;“干的”;输出此.NETXML序列化代码
我有一个基集合类和一个子集合类,它们都是可序列化的。在一次测试中,我发现简单地使用子类的C# “救救我”;“干的”;输出此.NETXML序列化代码,c#,refactoring,xml-serialization,dry,C#,Refactoring,Xml Serialization,Dry,我有一个基集合类和一个子集合类,它们都是可序列化的。在一次测试中,我发现简单地使用子类的ReadXml方法调用base.ReadXml之后会导致InvalidCastException。首先,这里是类结构: 基类 // Collection of Row objects [Serializable] [XmlRoot("Rows")] public class Rows : IList<Row>, ICollection<Row>, IEnumerable<Row&
ReadXml
方法调用base.ReadXml
之后会导致InvalidCastException
。首先,这里是类结构:
基类
// Collection of Row objects
[Serializable]
[XmlRoot("Rows")]
public class Rows : IList<Row>, ICollection<Row>, IEnumerable<Row>,
IEquatable<Rows>, IXmlSerializable
{
public Collection<Row> Collection { get; protected set; }
public void ReadXml(XmlReader reader)
{
reader.ReadToFollowing(XmlNodeName);
do
{
using (XmlReader rowReader = reader.ReadSubtree())
{
var row = new Row();
row.ReadXml(rowReader);
Collection.Add(row);
}
} while (reader.ReadToNextSibling(XmlNodeName));
}
}
// Acts as a collection of SpecificRow objects, which inherit from Row. Uses the same
// Collection<Row> that Rows defines which is fine since SpecificRow : Row.
[Serializable]
[XmlRoot("MySpecificRowList")]
public class SpecificRows : Rows, IXmlSerializable
{
public new void ReadXml(XmlReader reader)
{
// Trying to just do base.ReadXml(reader) causes a cast exception later
reader.ReadToFollowing(XmlNodeName);
do
{
using (XmlReader rowReader = reader.ReadSubtree())
{
var row = new SpecificRow();
row.ReadXml(rowReader);
Collection.Add(row);
}
} while (reader.ReadToNextSibling(XmlNodeName));
}
public new Row this[int index]
{
// The cast in this getter is what causes InvalidCastException if I try
// to call base.ReadXml from this class's ReadXml
get { return (Row)Collection[index]; }
set { Collection[index] = value; }
}
}
因此,最重要的代码编译和运行时没有异常,但它让我觉得
Rows.ReadXml
和SpecificRows.ReadXml
本质上是相同的代码。XmlNodeName
的值和new Row()
/new specific Row()
的值是不同之处。您建议我如何提取这两个版本的ReadXml
的所有通用功能?仅仅为一个方法创建一些泛型类是愚蠢的吗?很抱歉代码示例太长,我只是想说明我不能简单地调用base.ReadXml
的原因,因为SpecificRows
当集合只能包含行
对象时,为什么要进行强制转换?也许我错过了什么
更新:
Collection[index] as Row;
将绕过异常,但它可能仍然不会产生您想要的结果(即:一个null而不是一行)
更新:
将基础重构为:
public void ReadXml<T>(XmlReader reader) where T : IRow
{
reader.ReadToFollowing(XmlNodeName);
do
{
using (XmlReader rowReader = reader.ReadSubtree())
{
var row = default(T);
row.ReadXml(rowReader);
Collection.Add(row);
}
} while (reader.ReadToNextSibling(XmlNodeName));
}
public-void-ReadXml(XmlReader-reader),其中T:IRow
{
reader.ReadToFollowing(XmlNodeName);
做
{
使用(XmlReader rowReader=reader.ReadSubtree())
{
var行=默认值(T);
ReadXml(rowleader);
集合。添加(行);
}
}while(reader.ReadToNextSibling(XmlNodeName));
}
为您工作?当集合
只能包含行
对象时,您为什么要进行强制转换?也许我错过了什么
更新:
Collection[index] as Row;
将绕过异常,但它可能仍然不会产生您想要的结果(即:一个null而不是一行)
更新:
将基础重构为:
public void ReadXml<T>(XmlReader reader) where T : IRow
{
reader.ReadToFollowing(XmlNodeName);
do
{
using (XmlReader rowReader = reader.ReadSubtree())
{
var row = default(T);
row.ReadXml(rowReader);
Collection.Add(row);
}
} while (reader.ReadToNextSibling(XmlNodeName));
}
public-void-ReadXml(XmlReader-reader),其中T:IRow
{
reader.ReadToFollowing(XmlNodeName);
做
{
使用(XmlReader rowReader=reader.ReadSubtree())
{
var行=默认值(T);
ReadXml(rowleader);
集合。添加(行);
}
}while(reader.ReadToNextSibling(XmlNodeName));
}
为你工作?看起来唯一的区别是这一行:
var row = new Row();
vs
因此,您可以将其提取到一个虚拟函数中,例如,MakeRow()
,然后ReadXml()
可以不重复。看起来唯一的区别是这一行:
var row = new Row();
vs
因此,您可以将其提取到一个虚拟函数中,例如,MakeRow()
,然后ReadXml()
可以不重复。如果您想这样做,您可以
public void ReadXml<T>(XmlReader reader) where T : IRow, new()
{
reader.ReadToFollowing(XmlNodeName);
do
{
using (XmlReader rowReader = reader.ReadSubtree())
{
var row = new T();
row.ReadXml(rowReader);
Collection.Add(row);
}
} while (reader.ReadToNextSibling(XmlNodeName));
}
然后在
// Acts as a collection of SpecificRow objects, which inherit from Row. Uses the same
// Collection<Row> that Rows defines which is fine since SpecificRow : Row.
[Serializable]
[XmlRoot("MySpecificRowList")]
public class SpecificRows : Rows, IXmlSerializable
{
protected override Row CreateRow()
{
return new SpecificRow();
}
}
//充当从行继承的SpecificRow对象的集合。使用相同的
//集合,该集合定义了自SpecificRow:Row以来哪些是正确的。
[可序列化]
[XmlRoot(“MySpecificRowList”)]
公共类SpecificRows:行,IXmlSerializable
{
受保护的重写行CreateRow()
{
返回新的SpecificRow();
}
}
如果此[]
方法返回行
类型,则不需要重写它。基类已经可以这样做了
如果希望this[]
返回SpecificRow
,那么在这个派生类中,可以安全地直接强制转换到该行。。。然而。。。为什么使用它的代码需要知道它处理的是什么类型的行?如果有,那么我会尝试对行对象应用“tell-don-ask”,这样行的使用者就不知道它正在与哪种类型的行对话,再次消除了对该方法的需要。如果要这样做,可以
public void ReadXml<T>(XmlReader reader) where T : IRow, new()
{
reader.ReadToFollowing(XmlNodeName);
do
{
using (XmlReader rowReader = reader.ReadSubtree())
{
var row = new T();
row.ReadXml(rowReader);
Collection.Add(row);
}
} while (reader.ReadToNextSibling(XmlNodeName));
}
然后在
// Acts as a collection of SpecificRow objects, which inherit from Row. Uses the same
// Collection<Row> that Rows defines which is fine since SpecificRow : Row.
[Serializable]
[XmlRoot("MySpecificRowList")]
public class SpecificRows : Rows, IXmlSerializable
{
protected override Row CreateRow()
{
return new SpecificRow();
}
}
//充当从行继承的SpecificRow对象的集合。使用相同的
//集合,该集合定义了自SpecificRow:Row以来哪些是正确的。
[可序列化]
[XmlRoot(“MySpecificRowList”)]
公共类SpecificRows:行,IXmlSerializable
{
受保护的重写行CreateRow()
{
返回新的SpecificRow();
}
}
如果此[]
方法返回行
类型,则不需要重写它。基类已经可以这样做了
如果希望this[]
返回SpecificRow
,那么在这个派生类中,可以安全地直接强制转换到该行。。。然而。。。为什么使用它的代码需要知道它处理的是什么类型的行?如果是这样,那么我将尝试对行对象应用“告诉不要问”,这样行的使用者就不知道它正在与哪种类型的行交谈,再次消除了对该方法的需要。更新了问题SpecificRows
充当SpecificRow
对象和SpecificRow:Row
的集合。是的,我尝试了作为
运算符,但没有得到InvalidCastException,但是当我得到null
而不是我所期望的行时,我仍然得到了一个异常。但是,是的,我已经解决了这个问题--演员阵容不是我要问的问题。我想将工作的ReadXml
方法重构到它们仍然可以工作的地方,但不要复制太多的代码。哦,我现在明白了,我可能有一个主意可以帮上忙。default(t)
如果t
是一个参考类型更新的问题,那么ReadXml
将返回null
SpecificRows
充当SpecificRow
对象和SpecificRow:Row
的集合。是的,我尝试了作为
操作符,但没有得到InvalidCastException,但是当我得到null
而不是我期望的行时,我仍然得到了一个异常。但是,是的,我已经修复了p