试图抽象我的程序,我使用f界多态来定义我的值。我使用DataContractJsonSerializer
(别无选择)。唯一的问题是,显然对于泛型,它会抛出一个XmlException
,说类型名称的格式不正确(下面末尾的第 5 行)。
public abstract class Value<T> where T : Value<T> {
}
public class StringValue : Value<StringValue> {
[DataMember]
public string S { get; set; }
}
[DataContract, KnownType("GetSubclasses")]
public abstract class Tree<TValue> where TValue : Value<TValue> {
public static IEnumerable<Type> GetSubclasses() {
return from t in typeof(Tree<>).Assembly.GetTypes()
where typeof(Tree<>).IsAssignableFrom(t)
select t;
}
[DataMember]
public string Name;
protected Tree() {}
}
[DataContract]
public class ConcTree<TValue> : Tree<TValue> where TValue : Value<TValue> {
[DataMember]
public TValue Value;
public ConcTree(string n, TValue reg) {
Name = n;
Value = reg;
}
}
var result = new ConcTree<StringValue>("test", new StringValue() { S = "s_value" });
var serializer = new DataContractJsonSerializer(typeof (Tree<StringValue>));
using (var stream = new MemoryStream()) {
serializer.WriteObject(stream, result); // Here XmlException
stream.Position = 0;
using (var reader = new StreamReader(stream))
return reader.ReadToEnd();
}
它抛出一个XmlException
或一个System.InvalidOperationException
,取决于一些参数。
名称中不能包含"{"字符(十六进制值0x7B)。"} System.Exception {System.Xml.XmlException}
调试变量时,我发现:
localName "TreeOf{0}{#}" string
在名为 IsValidNCName 的函数中进行测试。如何克服这些异常?在使用泛型之前,我从未拥有过它们,但我不想回去。
--编辑--
我试图使用new DataContractJsonSerializer(typeof (ConcTree<StringValue>));
以便它采用正确的类型,但没有成功。
经过36小时的搜索,我终于找到了正确的方法。我不是在程序集中查找已注册的类型,而是向注册其类型的Tree
的所有子类添加一个静态初始值设定项。
此外,如果我有一个高级类层次结构,我必须将通用参数TValue
添加到已知类型列表中(参见 #1),尤其是对于反序列化。请参阅最后一部分。
[DataContract, KnownType("GetKnownSubclassesOfRegion")]
public abstract class Value<T> where T : Value<T> {
//Register sub-types statically.
protected static readonly List<Type> ValueTypes= new List<Type>();
public static IEnumerable<Type> GetKnownSubclassesOfRegion() {
return RegionTypes;
}
}
[DataContract]
public class StringValue : Value<StringValue> {
[DataMember]
public string S { get; set; }
static StringValue() {
ValueTypes.Add(typeof(StringValue ));
}
}
树也是如此:
[DataContract, KnownType("GetSubclasses")]
public abstract class Tree<TValue> where TValue : Value<TValue> {
//Register sub-types statically with their generic parameter which is instantiated.
protected static readonly List<Type> RegisteredTypes = new List<Type>();
public static IEnumerable<Type> GetSubclasses() { //This is new
return RegisteredTypes;
}
static TreeElement() { // #1
RegisteredTypes.Add(typeof(TValue));
}
[DataMember]
public string Name;
protected Tree() {}
}
[DataContract]
public class ConcTree<TValue> : Tree<TValue> where TValue : Value<TValue> {
[DataMember]
public TValue Value;
public ConcTree(string n, TValue reg) {
Name = n;
Value = reg;
}
static ConcTree() { //This is new
ValueTypes.Add(typeof(ConcTree<TValue>));
}
}
var result = new ConcTree<StringValue>("test", new StringValue() { S = "s_value" });
var serializer = new DataContractJsonSerializer(typeof (Tree<StringValue>));
using (var stream = new MemoryStream()) {
serializer.WriteObject(stream, result); // No exception anymore.
stream.Position = 0;
using (var reader = new StreamReader(stream))
return reader.ReadToEnd();
}
现在它工作得很好!