Skip to content

Commit

Permalink
Separate IObjectDescriptor from IPropertyDescriptor to isolate access…
Browse files Browse the repository at this point in the history
…ors from metadata.
  • Loading branch information
aaubry committed Mar 18, 2014
1 parent 4efc1f6 commit b2abe20
Show file tree
Hide file tree
Showing 14 changed files with 55 additions and 45 deletions.
6 changes: 5 additions & 1 deletion YamlDotNet.Test/Serialization/SerializationTestHelper.cs
Expand Up @@ -378,7 +378,11 @@ public Example()
public class IgnoreExample
{
[YamlIgnore]
public String IgnoreMe { get; set; }
public String IgnoreMe
{
get { throw new NotImplementedException("Accessing a [YamlIgnore] property"); }
set { throw new NotImplementedException("Accessing a [YamlIgnore] property"); }
}
}

public class DefaultsExample
Expand Down
2 changes: 1 addition & 1 deletion YamlDotNet.Test/Serialization/SerializationTests.cs
Expand Up @@ -564,7 +564,7 @@ public void DeserializationOfDefaultsWorkInJson()
public void SerializationRespectsYamlIgnoreAttribute()
{
var writer = new StringWriter();
var obj = new IgnoreExample { IgnoreMe = "Some Text" };
var obj = new IgnoreExample();

Serializer.Serialize(writer, obj);
var serialized = writer.ToString();
Expand Down
2 changes: 1 addition & 1 deletion YamlDotNet.build
Expand Up @@ -4,7 +4,7 @@
<!-- This build file requires .NET 4.0 and nant 0.91 alpha 2 or higher -->
<property name="nant.settings.currentframework" value="net-4.0"/>

<property name="version" value="3.1.0" />
<property name="version" value="3.1.1" />

<fileset id="binaries">
<include name="YamlDotNet/bin/Release/YamlDotNet.dll" />
Expand Down
2 changes: 1 addition & 1 deletion YamlDotNet/Serialization/IObjectGraphVisitor.cs
Expand Up @@ -53,7 +53,7 @@ public interface IObjectGraphVisitor
/// <param name="key">The <see cref="IPropertyDescriptor"/> that provided access to <paramref name="value"/>.</param>
/// <param name="value">The value of the mapping that is about to be entered.</param>
/// <returns>If the mapping is to be entered, returns true; otherwise returns false;</returns>
bool EnterMapping(IPropertyDescriptor key, object value);
bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value);

/// <summary>
/// Notifies the visitor that a scalar value has been encountered.
Expand Down
9 changes: 6 additions & 3 deletions YamlDotNet/Serialization/IPropertyDescriptor.cs
Expand Up @@ -23,13 +23,16 @@

namespace YamlDotNet.Serialization
{
public interface IPropertyDescriptor : IObjectDescriptor
public interface IPropertyDescriptor
{
string Name { get; }
bool CanWrite { get; }

void SetValue(object target, object value);
Type Type { get; }
Type TypeOverride { get; set; }

T GetCustomAttribute<T>() where T : Attribute;

IObjectDescriptor Read(object target);
void Write(object target, object value);
}
}
Expand Up @@ -67,15 +67,15 @@ bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func<E
if (propertyValuePromise == null)
{
var convertedValue = TypeConverter.ChangeType(propertyValue, property.Type);
property.SetValue(value, convertedValue);
property.Write(value, convertedValue);
}
else
{
var valueRef = value;
propertyValuePromise.ValueAvailable += v =>
{
var convertedValue = TypeConverter.ChangeType(v, property.Type);
property.SetValue(valueRef, convertedValue);
property.Write(valueRef, convertedValue);
};
}
}
Expand Down
Expand Up @@ -228,12 +228,12 @@ protected virtual void TraverseProperties(IObjectDescriptor value, IObjectGraphV

foreach (var propertyDescriptor in typeDescriptor.GetProperties(value.Type, value.Value))
{
var propertyValue = propertyDescriptor.Value;
var propertyValue = propertyDescriptor.Read(value.Value);

if (visitor.EnterMapping(propertyDescriptor, propertyValue))
{
Traverse(new ObjectDescriptor(propertyDescriptor.Name, typeof(string), typeof(string)), visitor, currentDepth);
Traverse(propertyDescriptor, visitor, currentDepth);
Traverse(propertyValue, visitor, currentDepth);
}
}

Expand Down
Expand Up @@ -65,7 +65,7 @@ bool IObjectGraphVisitor.EnterMapping(IObjectDescriptor key, IObjectDescriptor v
return true;
}

bool IObjectGraphVisitor.EnterMapping(IPropertyDescriptor key, object value)
bool IObjectGraphVisitor.EnterMapping(IPropertyDescriptor key, IObjectDescriptor value)
{
return true;
}
Expand Down
Expand Up @@ -42,7 +42,7 @@ public virtual bool EnterMapping(IObjectDescriptor key, IObjectDescriptor value)
return nextVisitor.EnterMapping(key, value);
}

public virtual bool EnterMapping(IPropertyDescriptor key, object value)
public virtual bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value)
{
return nextVisitor.EnterMapping(key, value);
}
Expand Down
Expand Up @@ -45,14 +45,14 @@ public override bool EnterMapping(IObjectDescriptor key, IObjectDescriptor value
&& base.EnterMapping(key, value);
}

public override bool EnterMapping(IPropertyDescriptor key, object value)
public override bool EnterMapping(IPropertyDescriptor key, IObjectDescriptor value)
{
var defaultValueAttribute = key.GetCustomAttribute<DefaultValueAttribute>();
var defaultValue = defaultValueAttribute != null
? defaultValueAttribute.Value
: GetDefault(key.Type);

return !_objectComparer.Equals(value, defaultValue)
return !_objectComparer.Equals(value.Value, defaultValue)
&& base.EnterMapping(key, value);
}
}
Expand Down
Expand Up @@ -42,7 +42,7 @@ bool IObjectGraphVisitor.EnterMapping(IObjectDescriptor key, IObjectDescriptor v
return true;
}

bool IObjectGraphVisitor.EnterMapping(IPropertyDescriptor key, object value)
bool IObjectGraphVisitor.EnterMapping(IPropertyDescriptor key, IObjectDescriptor value)
{
return true;
}
Expand Down
20 changes: 12 additions & 8 deletions YamlDotNet/Serialization/PropertyDescriptor.cs
Expand Up @@ -31,32 +31,36 @@ public PropertyDescriptor(IPropertyDescriptor baseDescriptor)
{
this.baseDescriptor = baseDescriptor;
Name = baseDescriptor.Name;
Type = baseDescriptor.Type;
StaticType = baseDescriptor.StaticType;
}

public string Name { get; set; }
public Type Type { get; set; }
public Type StaticType { get; set; }

public object Value
public Type Type { get { return baseDescriptor.Type; } }

public Type TypeOverride
{
get { return baseDescriptor.Value; }
get { return baseDescriptor.TypeOverride; }
set { baseDescriptor.TypeOverride = value; }
}

public bool CanWrite
{
get { return baseDescriptor.CanWrite; }
}

public void SetValue(object target, object value)
public void Write(object target, object value)
{
baseDescriptor.SetValue(target, value);
baseDescriptor.Write(target, value);
}

public T GetCustomAttribute<T>() where T : Attribute
{
return baseDescriptor.GetCustomAttribute<T>();
}

public IObjectDescriptor Read(object target)
{
return baseDescriptor.Read(target);
}
}
}
Expand Up @@ -31,16 +31,16 @@ namespace YamlDotNet.Serialization.TypeInspectors
/// </summary>
public sealed class ReadablePropertiesTypeInspector : TypeInspectorSkeleton
{
private readonly ITypeResolver _reflectionPropertyDescriptorFactory;
private readonly ITypeResolver _typeResolver;

public ReadablePropertiesTypeInspector(ITypeResolver reflectionPropertyDescriptorFactory)
public ReadablePropertiesTypeInspector(ITypeResolver typeResolver)
{
if (reflectionPropertyDescriptorFactory == null)
if (typeResolver == null)
{
throw new ArgumentNullException("reflectionPropertyDescriptorFactory");
throw new ArgumentNullException("typeResolver");
}

_reflectionPropertyDescriptorFactory = reflectionPropertyDescriptorFactory;
_typeResolver = typeResolver;
}

private static bool IsValidProperty(PropertyInfo property)
Expand All @@ -54,34 +54,26 @@ public override IEnumerable<IPropertyDescriptor> GetProperties(Type type, object
return type
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(IsValidProperty)
.Select(p =>
{
var propertyValue = container != null
? p.GetValue(container, null)
: null;
return (IPropertyDescriptor)new ReflectionPropertyDescriptor(p, _reflectionPropertyDescriptorFactory.Resolve(p.PropertyType, propertyValue), propertyValue);
});
.Select(p => (IPropertyDescriptor)new ReflectionPropertyDescriptor(p, _typeResolver));
}

private sealed class ReflectionPropertyDescriptor : IPropertyDescriptor
{
private readonly PropertyInfo _propertyInfo;
private readonly ITypeResolver _typeResolver;

public ReflectionPropertyDescriptor(PropertyInfo propertyInfo, Type type, object value)
public ReflectionPropertyDescriptor(PropertyInfo propertyInfo, ITypeResolver typeResolver)
{
_propertyInfo = propertyInfo;
Type = type;
Value = value;
_typeResolver = typeResolver;
}

public string Name { get { return _propertyInfo.Name; } }
public Type Type { get; private set; }
public Type StaticType { get { return _propertyInfo.PropertyType; } }
public object Value { get; private set; }
public Type Type { get { return _propertyInfo.PropertyType; } }
public Type TypeOverride { get; set; }
public bool CanWrite { get { return _propertyInfo.CanWrite; } }

public void SetValue(object target, object value)
public void Write(object target, object value)
{
_propertyInfo.SetValue(target, value, null);
}
Expand All @@ -93,6 +85,13 @@ public void SetValue(object target, object value)
? (T)attributes[0]
: null;
}

public IObjectDescriptor Read(object target)
{
var propertyValue = _propertyInfo.GetValue(target, null);
var actualType = TypeOverride ?? _typeResolver.Resolve(Type, propertyValue);
return new ObjectDescriptor(propertyValue, actualType, Type);
}
}
}
}
2 changes: 1 addition & 1 deletion YamlDotNet/Serialization/YamlAttributesTypeInspector.cs
Expand Up @@ -57,7 +57,7 @@ public override IEnumerable<IPropertyDescriptor> GetProperties(Type type, object
{
if (member.SerializeAs != null)
{
descriptor.Type = member.SerializeAs;
descriptor.TypeOverride = member.SerializeAs;
}
}
Expand Down

0 comments on commit b2abe20

Please sign in to comment.