Merge pull request #19 from roji/roundtrip_ctor

Can roundrip with type converter and no default ctor
This commit is contained in:
Antoine Aubry 2013-05-02 02:00:22 -07:00
Родитель 0d9b5a45bd 58f598236b
Коммит 995643d671
4 изменённых файлов: 59 добавлений и 18 удалений

Просмотреть файл

@ -13,15 +13,17 @@ namespace YamlDotNet.RepresentationModel.Serialization
/// </summary>
public class FullObjectGraphTraversalStrategy : IObjectGraphTraversalStrategy
{
protected readonly Serializer serializer;
private readonly int maxRecursion;
public FullObjectGraphTraversalStrategy(int maxRecursion)
public FullObjectGraphTraversalStrategy(Serializer serializer, int maxRecursion)
{
if(maxRecursion <= 0)
{
throw new ArgumentOutOfRangeException("maxRecursion", maxRecursion, "maxRecursion must be greater than 1");
}
this.serializer = serializer;
this.maxRecursion = maxRecursion;
}

Просмотреть файл

@ -1,5 +1,6 @@
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
namespace YamlDotNet.RepresentationModel.Serialization
@ -22,16 +23,16 @@ namespace YamlDotNet.RepresentationModel.Serialization
// base.TraverseObject(value, type, visitor);
//}
public RoundtripObjectGraphTraversalStrategy(int maxRecursion)
: base(maxRecursion)
public RoundtripObjectGraphTraversalStrategy(Serializer serializer, int maxRecursion)
: base(serializer, maxRecursion)
{
}
protected override void SerializeProperties(object value, Type type, IObjectGraphVisitor visitor, int currentDepth)
{
if (!ReflectionUtility.HasDefaultConstructor(type))
if (!ReflectionUtility.HasDefaultConstructor(type) && !serializer.Converters.Any(c => c.Accepts(type)))
{
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Type '{0}' cannot be deserialized because it does not have a default constructor.", type));
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Type '{0}' cannot be deserialized because it does not have a default constructor or a type converter.", type));
}
base.SerializeProperties(value, type, visitor, currentDepth);

Просмотреть файл

@ -71,14 +71,19 @@ namespace YamlDotNet.RepresentationModel.Serialization
/// </summary>
public sealed class Serializer
{
private readonly IList<IYamlTypeConverter> converters = new List<IYamlTypeConverter>();
internal IList<IYamlTypeConverter> Converters { get; private set; }
public Serializer()
{
Converters = new List<IYamlTypeConverter>();
}
/// <summary>
/// Registers a type converter to be used to serialize and deserialize specific types.
/// </summary>
public void RegisterTypeConverter(IYamlTypeConverter converter)
{
converters.Add(converter);
Converters.Add(converter);
}
/// <summary>
@ -155,7 +160,7 @@ namespace YamlDotNet.RepresentationModel.Serialization
{
IObjectGraphVisitor emittingVisitor = new EmittingObjectGraphVisitor(eventEmitter);
emittingVisitor = new CustomSerializationObjectGraphVisitor(emitter, emittingVisitor, converters);
emittingVisitor = new CustomSerializationObjectGraphVisitor(emitter, emittingVisitor, Converters);
if ((options & SerializationOptions.DisableAliases) == 0)
{
@ -191,11 +196,11 @@ namespace YamlDotNet.RepresentationModel.Serialization
{
if ((options & SerializationOptions.Roundtrip) != 0)
{
return new RoundtripObjectGraphTraversalStrategy(50);
return new RoundtripObjectGraphTraversalStrategy(this, 50);
}
else
{
return new FullObjectGraphTraversalStrategy(50);
return new FullObjectGraphTraversalStrategy(this, 50);
}
}
}

Просмотреть файл

@ -23,6 +23,7 @@ using System;
using System.Drawing;
using Xunit;
using System.IO;
using YamlDotNet.Core;
using YamlDotNet.RepresentationModel.Serialization;
using System.Reflection;
using System.Collections;
@ -554,15 +555,47 @@ namespace YamlDotNet.UnitTests.RepresentationModel
#endregion
}
//[Fact]
//public void DeserializeTypeConverter()
//{
// YamlSerializer<Z> serializer = new YamlSerializer<Z>();
// object result = serializer.Deserialize(YamlFile("converter.yaml"));
class SomeCustomeType
{
// Test specifically with no parameterless, supposed to fail unless a type converter is specified
public SomeCustomeType(string value) { Value = value; }
public string Value;
}
// Assert.True(typeof(Z).IsAssignableFrom(result.GetType()));
// Assert.Equal("[hello, world]", ((Z)result).aaa, "The property has the wrong value.");
//}
public class CustomTypeConverter : IYamlTypeConverter
{
public bool Accepts(Type type) { return type == typeof(SomeCustomeType); }
public object ReadYaml(Parser parser, Type type)
{
var value = ((Scalar)parser.Current).Value;
parser.MoveNext();
return new SomeCustomeType(value);
}
public void WriteYaml(Emitter emitter, object value, Type type)
{
emitter.Emit(new Scalar(((SomeCustomeType)value).Value));
}
}
[Fact]
public void RoundtripWithTypeConverter()
{
SomeCustomeType x = new SomeCustomeType("Yo");
var serializer = new Serializer();
serializer.RegisterTypeConverter(new CustomTypeConverter());
StringWriter buffer = new StringWriter();
serializer.Serialize(buffer, x, SerializationOptions.Roundtrip);
Console.WriteLine(buffer.ToString());
var deserializer = new YamlSerializer<SomeCustomeType>(YamlSerializerModes.Roundtrip);
deserializer.RegisterTypeConverter(new CustomTypeConverter());
var copy = deserializer.Deserialize(new StringReader(buffer.ToString()));
Assert.Equal("Yo", copy.Value);
}
[Fact]
public void RoundtripDictionary()