我有一个基类SpecialClass
。许多其他类继承自它,如WriteSpecialClass
和ReadSpecialClass
。在将这些类转换为基类之后,将对这些类的实例进行序列化和反序列化。因此,我有很多这样的重复代码(用于序列化):
SpecialClass sc = null;
if (type.DisplayName == "Read") {
sc = new ReadSpecialClass();
} else if (type.DisplayName == "Write") {
sc = new WriteSpecialClass();
} else
throw new NotSupportedException("Type not supported");
String xml = SerializeToXML(sc);
..和反序列化:
SpecialClass sc = null;
sc = (SpecialClass)DeserializeFromXML(xml);
switch (someVariableThatDicatesTypeOfSpecialClass) {
case "Read":
sc = (ReadSpecialClass)sc;
break;
case "Write":
sc = (WriteSpecialClass)sc;
break;
}
另一个重要的信息:SpecialClass
定义了一堆抽象方法,每个从中继承的类都需要实现。从它继承的所有类都符合方法,但返回不同的东西,所以每个类都不一样。
如果需要,我可以发布序列化或反序列化方法。
我想尝试简化这一点,这样我就不必指定每个SpecialClass
派生类(如ReadSpecialClass
)。有没有办法做到这一点?我能想到的唯一方法是打鸭。谢谢你的帮助,
答案 0 :(得分:3)
您是否考虑过SpecialClass中的serialize()方法?这样,如果有一些特殊注意事项,您可以覆盖base.serialize方法并处理任何独特需求。通过这种方式,它已经知道它是什么,并且条件不是必需的。
另一件需要考虑的事情可能是具有立面图案的辅助类。然后你可以有一个名为“public SpecialClass DeserializeSpecialClass()”的方法。然后,您可以将其转换为目标,而不是在反序列化器中转换类型。如果你发现你做了太多的转换,那么可以考虑将抽象方法添加到将在派生类中实现的基类。
希望这有帮助。
答案 1 :(得分:2)
对于序列化,您可以使用某种查找:
public class SpecialClass
{
private static Dictionary<string, Func<SpecialClass>> factories =
new Dictionary<string, Func<SpecialClass>>();
static SpecialClass()
{
factories["Read"] = () => new ReadSpecialClass();
factories["Write"] = () => new WriteSpecialClass();
}
public static SpecialClass CreateByName(string name)
{
Func<SpecialClass> factory;
if (!factories.TryGetValue(name))
throw new ArgumentException("name", "\"" name +
"\" is not a recognized subclass of SpecialClass.");
return factory();
}
}
对于反序列化,这两行:
sc = (ReadSpecialClass)sc;
sc = (WriteSpecialClass)sc;
不执行实际转换。如果sc
引用的对象不是合适的类型,他们唯一要做的就是抛出异常。你在这里做的几乎与:
object a = "foo";
a = (string)a;
当然,演员会成功。但它不会以任何方式修改a
指向的对象。它真正做的就是验证这个对象已经是一个字符串。
答案 2 :(得分:0)
if (sc is WriteSpecialClass)
{
sc = (WriteSpecialClass) sc;
}
else if (sc is ReadSpecialClass)
{
sc = (ReadSpecialClass) sc;
}
else
{
throw new NotSupportetException("Type not Supportet");
}
答案 3 :(得分:0)
如果您不关心性能,可以使用反射初始化名称中包含该类型名称的类型。
SerializeToXML()
将基类SpecialClass
作为参数,因此不应区分派生类ReadSpecialClass
和WriteSpecialClass
之间的差异。为什么不将SerializeToXML()
作为基类的实例方法?
答案 4 :(得分:0)
规则1. /您的派生类应负责自行序列化和反序列化,因为它们应该是唯一熟悉XML文档中存储的附加数据的人。
所以从ploymorphic的角度来看(注意你上面的代码不是多态的)你会做类似的事情
public class SpecialClass
{
public virtual XElement SerializeToXML()
{
// Base impl
}
}
public class YourDerivedClasses
{
public override XElement SerializeToXML()
{
//derived implementation
}
}
非常直接。但是你遇到的问题不是序列化或多态行为,而是XML中正确类型的实例化。
解决该问题的一种方法是在XML文档中使用一些键来指定保存它的类型,并注册一个负责构造由该键索引的派生类型的工厂(属性适用于那种注册) ),一旦构造派生类型,用它来反序列化xml。
注意,您的工厂也可以是Base类的静态方法。
类似的东西,(当然未经测试)......
public class SpecialClass
{
***snip
public static IEnumerable<SpecialClass> GetAllClasses(XElement xml)
{
IDictionary keyedtypes = GetKeyedTypesDictUsingReflection() // the registered factories
foreach(var x in xml.Elements("YourClassesNode"))
{
string key = //get key from xml
yield return keyedTypes[key].DeserializeFromXML(x);
}
}
}