[英]How can I solve this C# polymorphism problem?
我有一个基类, 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
)。 有什么办法吗? 我能想到的唯一方法就是打字。 谢谢你的帮助,
您是否考虑过SpecialClass中的serialize()方法? 这样,如果有一些特殊的考虑,您可以覆盖base.serialize方法并照顾任何独特的需求。 通过这种方式,它已经知道它是什么,而没有条件。
要考虑的另一件事可能是带有外观模式的帮助程序类。 然后,您可以使用一个称为“ public SpecialClass DeserializeSpecialClass()”的方法。 然后,可以将其强制转换为目标,而不是将其转换为反序列化器。 如果发现您进行了过多的转换,则可以考虑将抽象方法添加到将在派生类中实现的基类。
希望这可以帮助。
对于序列化,可以使用某种查找:
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
指向的对象。 它真正要做的就是验证该对象已经是一个字符串。
if (sc is WriteSpecialClass)
{
sc = (WriteSpecialClass) sc;
}
else if (sc is ReadSpecialClass)
{
sc = (ReadSpecialClass) sc;
}
else
{
throw new NotSupportetException("Type not Supportet");
}
如果您不关心性能,则可以使用反射来初始化名称包含该类型名称的类型。
SerializeToXML()
将基类SpecialClass
作为参数,因此不应区分派生类ReadSpecialClass
和WriteSpecialClass
之间的WriteSpecialClass
。 为什么不将SerializeToXML()
作为基类的实例方法?
规则1. /您的派生类应该负责自己的序列化和反序列化,因为它们应该是唯一了解XML Doc中存储的其他数据的类。
因此,从多态性的角度来看(请注意,上面的代码不是多态的),您将执行以下操作
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);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.