如何将 C# 中的类型 class 对象序列化和反序列化为 YAML?
How to Serialize and Deserialize a Type class object in C# into YAML?
我有一个要求,我必须将以下类型层次结构序列化为 YAML
var Variable1 = new
{
Name = "Variable1",
Type = typeof(Int32),
OverWrite = true,
Value = 10
};
var Variable2 = new
{
Name = "Variable1",
Type = typeof(Int32),
OverWrite = true,
Value = 10
};
var Job = new
{
Name = "Job1",
JobID = 1,
JobState = "Draft",
JobStatus = false,
Parameters = new[]
{
Variable1,
Variable2
},
LocalVariables = new[]
{
Variable1
}
};
这里我得到一个异常
An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
附加信息:调用目标抛出异常。{"Method may only be called on a Type for which Type.IsGenericParameter is true."}
请帮忙!!
这是因为您正在尝试序列化 System.Type
。该类型有很多属性,其中一些会抛出您所看到的异常。这在 issue #212 上进行了讨论,尽管在那种情况下修复是为了完全避免序列化 System.Type
。
理想情况下,您可以注册自定义类型转换器来处理 System.Type
并将其序列化为字符串,但由于 a shortcoming with the way the object graph is traversed,属性 仍将被访问.
您最好的解决方案可能是将 System.Type
包装在自定义的 class 中,并根据需要进行序列化:
public struct SerializableType : IYamlConvertible
{
private Type type;
void IYamlConvertible.Read(IParser parser, Type expectedType, ObjectDeserializer nestedObjectDeserializer)
{
var typeName = (string)nestedObjectDeserializer(typeof(string));
type = typeName != null ? Type.GetType(typeName) : null;
}
void IYamlConvertible.Write(IEmitter emitter, ObjectSerializer nestedObjectSerializer)
{
nestedObjectSerializer(type != null ? type.AssemblyQualifiedName : null);
}
public static implicit operator Type(SerializableType value)
{
return value.type;
}
public static implicit operator SerializableType(Type value)
{
return new SerializableType { type = value };
}
}
编辑
提到的问题已经解决。如果你尝试 the latest pre-release package,你将能够通过注册自定义 IYamlTypeConverter
:
来实现你想要的
public class SystemTypeTypeConverter : IYamlTypeConverter
{
public bool Accepts(Type type)
{
return typeof(Type).IsAssignableFrom(type);
}
public object ReadYaml(IParser parser, Type type)
{
var scalar = parser.Expect<Scalar>();
return Type.GetType(scalar.Value);
}
public void WriteYaml(IEmitter emitter, object value, Type type)
{
var typeName = ((Type)value).AssemblyQualifiedName;
emitter.Emit(new Scalar(typeName));
}
}
// ....
var serializer = new SerializerBuilder()
.WithTypeConverter(new SystemTypeTypeConverter())
.Build();
var yaml = serializer.Serialize(new TypeContainer
{
Type = typeof(string),
});
var deserializer = new DeserializerBuilder()
.WithTypeConverter(new SystemTypeTypeConverter())
.Build();
var result = deserializer.Deserialize<TypeContainer>(yaml);
Assert.Equal(typeof(string), result.Type);
我有一个要求,我必须将以下类型层次结构序列化为 YAML
var Variable1 = new
{
Name = "Variable1",
Type = typeof(Int32),
OverWrite = true,
Value = 10
};
var Variable2 = new
{
Name = "Variable1",
Type = typeof(Int32),
OverWrite = true,
Value = 10
};
var Job = new
{
Name = "Job1",
JobID = 1,
JobState = "Draft",
JobStatus = false,
Parameters = new[]
{
Variable1,
Variable2
},
LocalVariables = new[]
{
Variable1
}
};
这里我得到一个异常
An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
附加信息:调用目标抛出异常。{"Method may only be called on a Type for which Type.IsGenericParameter is true."}
请帮忙!!
这是因为您正在尝试序列化 System.Type
。该类型有很多属性,其中一些会抛出您所看到的异常。这在 issue #212 上进行了讨论,尽管在那种情况下修复是为了完全避免序列化 System.Type
。
理想情况下,您可以注册自定义类型转换器来处理 System.Type
并将其序列化为字符串,但由于 a shortcoming with the way the object graph is traversed,属性 仍将被访问.
您最好的解决方案可能是将 System.Type
包装在自定义的 class 中,并根据需要进行序列化:
public struct SerializableType : IYamlConvertible
{
private Type type;
void IYamlConvertible.Read(IParser parser, Type expectedType, ObjectDeserializer nestedObjectDeserializer)
{
var typeName = (string)nestedObjectDeserializer(typeof(string));
type = typeName != null ? Type.GetType(typeName) : null;
}
void IYamlConvertible.Write(IEmitter emitter, ObjectSerializer nestedObjectSerializer)
{
nestedObjectSerializer(type != null ? type.AssemblyQualifiedName : null);
}
public static implicit operator Type(SerializableType value)
{
return value.type;
}
public static implicit operator SerializableType(Type value)
{
return new SerializableType { type = value };
}
}
编辑
提到的问题已经解决。如果你尝试 the latest pre-release package,你将能够通过注册自定义 IYamlTypeConverter
:
public class SystemTypeTypeConverter : IYamlTypeConverter
{
public bool Accepts(Type type)
{
return typeof(Type).IsAssignableFrom(type);
}
public object ReadYaml(IParser parser, Type type)
{
var scalar = parser.Expect<Scalar>();
return Type.GetType(scalar.Value);
}
public void WriteYaml(IEmitter emitter, object value, Type type)
{
var typeName = ((Type)value).AssemblyQualifiedName;
emitter.Emit(new Scalar(typeName));
}
}
// ....
var serializer = new SerializerBuilder()
.WithTypeConverter(new SystemTypeTypeConverter())
.Build();
var yaml = serializer.Serialize(new TypeContainer
{
Type = typeof(string),
});
var deserializer = new DeserializerBuilder()
.WithTypeConverter(new SystemTypeTypeConverter())
.Build();
var result = deserializer.Deserialize<TypeContainer>(yaml);
Assert.Equal(typeof(string), result.Type);