зеркало из https://github.com/stride3d/SharpYaml.git
Start to rewrite serialization (WIP)
This commit is contained in:
Родитель
8bee539624
Коммит
df7c220db8
|
@ -66,7 +66,7 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
||||
<Project>{BF32DE1B-6276-4341-B212-F8862ADBBA7A}</Project>
|
||||
<Name>YamlDotNet.Core</Name>
|
||||
<Name>YamlDotNet</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
||||
<Project>{BF32DE1B-6276-4341-B212-F8862ADBBA7A}</Project>
|
||||
<Name>YamlDotNet.Core</Name>
|
||||
<Name>YamlDotNet</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
||||
<Project>{21CA0077-E15C-446D-9C43-F6D3F9D09687}</Project>
|
||||
|
|
|
@ -61,9 +61,9 @@
|
|||
<Project>{6a8dcaf7-6c13-4ada-aed9-7aba88fe7717}</Project>
|
||||
<Name>YamlDotNet.Converters</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\YamlDotNet.Core.Test\YamlDotNet.Core.Test.csproj">
|
||||
<ProjectReference Include="..\YamlDotNet.Core.Test\YamlDotNet.Test.csproj">
|
||||
<Project>{16d8043d-c3db-4868-bff3-b2ebdf537aaa}</Project>
|
||||
<Name>YamlDotNet.Core.Test</Name>
|
||||
<Name>YamlDotNet.Test</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
||||
<Project>{21ca0077-e15c-446d-9c43-f6d3f9d09687}</Project>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="FakeItEasy">
|
||||
<Reference Include="FakeItEasy">
|
||||
<HintPath>..\packages\FakeItEasy.1.13.1\lib\net40\FakeItEasy.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentAssertions">
|
||||
|
@ -100,11 +100,7 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
||||
<Project>{bf32de1b-6276-4341-b212-f8862adbba7a}</Project>
|
||||
<Name>YamlDotNet.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
||||
<Project>{21ca0077-e15c-446d-9c43-f6d3f9d09687}</Project>
|
||||
<Name>YamlDotNet.Serialzation</Name>
|
||||
<Name>YamlDotNet</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
@ -65,13 +65,13 @@
|
|||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\YamlDotNet.Core.Test\YamlDotNet.Core.Test.csproj">
|
||||
<ProjectReference Include="..\YamlDotNet.Core.Test\YamlDotNet.Test.csproj">
|
||||
<Project>{16d8043d-c3db-4868-bff3-b2ebdf537aaa}</Project>
|
||||
<Name>YamlDotNet.Core.Test</Name>
|
||||
<Name>YamlDotNet.Test</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
||||
<Project>{bf32de1b-6276-4341-b212-f8862adbba7a}</Project>
|
||||
<Name>YamlDotNet.Core</Name>
|
||||
<Name>YamlDotNet</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
||||
<Project>{21ca0077-e15c-446d-9c43-f6d3f9d09687}</Project>
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
||||
<Project>{BF32DE1B-6276-4341-B212-F8862ADBBA7A}</Project>
|
||||
<Name>YamlDotNet.Core</Name>
|
||||
<Name>YamlDotNet</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
||||
<Project>{21CA0077-E15C-446D-9C43-F6D3F9D09687}</Project>
|
||||
|
|
|
@ -34,14 +34,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{8DC198
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.Converters.Test", "YamlDotNet.Converters.Test\YamlDotNet.Converters.Test.csproj", "{F0EAB124-9790-41C7-AE0F-F050CA0141D3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.Core.Test", "YamlDotNet.Core.Test\YamlDotNet.Core.Test.csproj", "{16D8043D-C3DB-4868-BFF3-B2EBDF537AAA}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.Test", "YamlDotNet.Core.Test\YamlDotNet.Test.csproj", "{16D8043D-C3DB-4868-BFF3-B2EBDF537AAA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.RepresentationModel.Test", "YamlDotNet.RepresentationModel.Test\YamlDotNet.RepresentationModel.Test.csproj", "{FF969DAA-C025-4636-89B2-46F16821FA02}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.Dynamic", "YamlDotNet.Dynamic\YamlDotNet.Dynamic.csproj", "{57B52D79-04A0-4091-8EE2-B419C009C2A6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestTag", "TestTag\TestTag.csproj", "{453D508D-E938-4C75-A852-05A05945472E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.Dynamic.UnitTests", "YamlDotNet.Dynamic.UnitTests\YamlDotNet.Dynamic.UnitTests.csproj", "{6E3BEF5A-2DBA-4941-972D-BD6AF27B4A71}"
|
||||
EndProject
|
||||
Global
|
||||
|
@ -113,6 +111,7 @@ Global
|
|||
{16D8043D-C3DB-4868-BFF3-B2EBDF537AAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{16D8043D-C3DB-4868-BFF3-B2EBDF537AAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{16D8043D-C3DB-4868-BFF3-B2EBDF537AAA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{16D8043D-C3DB-4868-BFF3-B2EBDF537AAA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{16D8043D-C3DB-4868-BFF3-B2EBDF537AAA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{16D8043D-C3DB-4868-BFF3-B2EBDF537AAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{16D8043D-C3DB-4868-BFF3-B2EBDF537AAA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
|
@ -137,15 +136,6 @@ Global
|
|||
{57B52D79-04A0-4091-8EE2-B419C009C2A6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{57B52D79-04A0-4091-8EE2-B419C009C2A6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{57B52D79-04A0-4091-8EE2-B419C009C2A6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{453D508D-E938-4C75-A852-05A05945472E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{453D508D-E938-4C75-A852-05A05945472E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{453D508D-E938-4C75-A852-05A05945472E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{453D508D-E938-4C75-A852-05A05945472E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{453D508D-E938-4C75-A852-05A05945472E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{453D508D-E938-4C75-A852-05A05945472E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{453D508D-E938-4C75-A852-05A05945472E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{453D508D-E938-4C75-A852-05A05945472E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{453D508D-E938-4C75-A852-05A05945472E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6E3BEF5A-2DBA-4941-972D-BD6AF27B4A71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6E3BEF5A-2DBA-4941-972D-BD6AF27B4A71}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6E3BEF5A-2DBA-4941-972D-BD6AF27B4A71}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
|
|
|
@ -20,15 +20,12 @@
|
|||
// SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using YamlDotNet;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception that is thrown when an alias references an anchor that does not exist.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class AnchorNotFoundException : YamlException
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// A descriptor for an array.
|
||||
/// </summary>
|
||||
public class ArrayDescriptor : ObjectDescriptor
|
||||
{
|
||||
private readonly Type elementType;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ObjectDescriptor" /> class.
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
public ArrayDescriptor(YamlSerializerSettings settings, Type type)
|
||||
: base(settings, type)
|
||||
{
|
||||
if (!type.IsArray) throw new ArgumentException("Expecting arrat type", "type");
|
||||
|
||||
elementType = type.GetElementType();
|
||||
|
||||
// TODO handle dimensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the array element.
|
||||
/// </summary>
|
||||
/// <value>The type of the element.</value>
|
||||
public Type ElementType { get { return elementType; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a descriptor for a <see cref="System.Collections.ICollection"/>.
|
||||
/// </summary>
|
||||
public class CollectionDescriptor : ObjectDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CollectionDescriptor" /> class.
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
public CollectionDescriptor(YamlSerializerSettings settings, Type type) : base(settings, type)
|
||||
{
|
||||
}
|
||||
|
||||
protected override List<IMemberDescriptor> PrepareMembers()
|
||||
{
|
||||
var members = base.PrepareMembers();
|
||||
|
||||
// In case we are not emitting List.Capacity, we need to remove them from the member list
|
||||
if (!Settings.EmitCapacityForList)
|
||||
{
|
||||
for (int i = members.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (members[i].Name == "Capacity" && members[i].Type == typeof (int))
|
||||
{
|
||||
members.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return members;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// A default implementation for <see cref="IAttributeRegistry"/>.
|
||||
/// This implementation allows to retrieve default attributes for a member or
|
||||
/// to attach an attribute to a specific type/member.
|
||||
/// </summary>
|
||||
public class DefaultAttributeRegistry : IAttributeRegistry
|
||||
{
|
||||
private readonly Dictionary<MemberInfoKey, List<Attribute>> cachedAttributes = new Dictionary<MemberInfoKey, List<Attribute>>();
|
||||
private readonly Dictionary<MemberInfo, List<Attribute>> registeredAttributes = new Dictionary<MemberInfo, List<Attribute>>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attributes associated with the specified member.
|
||||
/// </summary>
|
||||
/// <param name="memberInfo">The reflection member.</param>
|
||||
/// <param name="inherit">if set to <c>true</c> includes inherited attributes.</param>
|
||||
/// <returns>An enumeration of <see cref="Attribute"/>.</returns>
|
||||
public List<Attribute> GetAttributes(MemberInfo memberInfo, bool inherit = true)
|
||||
{
|
||||
var key = new MemberInfoKey(memberInfo, inherit);
|
||||
|
||||
// Use a cache of attributes
|
||||
List<Attribute> attributes;
|
||||
if (cachedAttributes.TryGetValue(key, out attributes))
|
||||
{
|
||||
return attributes;
|
||||
}
|
||||
|
||||
// Else retrieve all default attributes
|
||||
var defaultAttributes = memberInfo.GetCustomAttributes(inherit);
|
||||
attributes = defaultAttributes.Cast<Attribute>().ToList();
|
||||
|
||||
// And add registered attributes
|
||||
List<Attribute> registered;
|
||||
if (registeredAttributes.TryGetValue(memberInfo, out registered))
|
||||
{
|
||||
attributes.AddRange(registered);
|
||||
}
|
||||
|
||||
// Add to the cache
|
||||
cachedAttributes.Add(key, attributes);
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attributes associated with the specified member.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the attribute</typeparam>
|
||||
/// <param name="memberInfo">The member information.</param>
|
||||
/// <param name="inherit">if set to <c>true</c> [inherit].</param>
|
||||
/// <returns>An enumeration of <see cref="Attribute"/>.</returns>
|
||||
public IEnumerable<T> GetAttributes<T>(MemberInfo memberInfo, bool inherit = true) where T : Attribute
|
||||
{
|
||||
return GetAttributes(memberInfo, inherit).OfType<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an attribute associated with the specified member.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the attribute</typeparam>
|
||||
/// <param name="memberInfo">The member information.</param>
|
||||
/// <param name="inherit">if set to <c>true</c> [inherit].</param>
|
||||
/// <returns>An attribute of type {T} if it was found; otherwise <c>null</c> </returns>
|
||||
public T GetAttribute<T>(MemberInfo memberInfo, bool inherit = true) where T : Attribute
|
||||
{
|
||||
var list = GetAttributes(memberInfo, inherit);
|
||||
if (list.Count > 0)
|
||||
{
|
||||
return list[list.Count - 1] as T;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers an attribute for the specified member. Restriction: Attributes registered this way cannot be listed in inherited attributes.
|
||||
/// </summary>
|
||||
/// <param name="memberInfo">The member information.</param>
|
||||
/// <param name="attribute">The attribute.</param>
|
||||
public void Register(MemberInfo memberInfo, Attribute attribute)
|
||||
{
|
||||
List<Attribute> attributes;
|
||||
if (!registeredAttributes.TryGetValue(memberInfo, out attributes))
|
||||
{
|
||||
attributes = new List<Attribute>();
|
||||
registeredAttributes.Add(memberInfo, attributes);
|
||||
}
|
||||
|
||||
attributes.Add(attribute);
|
||||
}
|
||||
|
||||
private struct MemberInfoKey : IEquatable<MemberInfoKey>
|
||||
{
|
||||
private readonly MemberInfo memberInfo;
|
||||
|
||||
private readonly bool inherit;
|
||||
|
||||
public MemberInfoKey(MemberInfo memberInfo, bool inherit)
|
||||
{
|
||||
this.memberInfo = memberInfo;
|
||||
this.inherit = inherit;
|
||||
}
|
||||
|
||||
public bool Equals(MemberInfoKey other)
|
||||
{
|
||||
return memberInfo.Equals(other.memberInfo) && inherit.Equals(other.inherit);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
return obj is MemberInfoKey && Equals((MemberInfoKey) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (memberInfo.GetHashCode()*397) ^ inherit.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Class DefaultDescriptorFactory.
|
||||
/// </summary>
|
||||
public class DefaultDescriptorFactory : ITypeDescriptorFactory
|
||||
{
|
||||
private readonly YamlSerializerSettings settings;
|
||||
protected readonly Dictionary<Type,ITypeDescriptor> RegisteredDescriptors = new Dictionary<Type, ITypeDescriptor>();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DefaultDescriptorFactory"/> class.
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings.</param>
|
||||
public DefaultDescriptorFactory(YamlSerializerSettings settings)
|
||||
{
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public virtual ITypeDescriptor Find(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
return null;
|
||||
|
||||
ITypeDescriptor descriptor;
|
||||
if (RegisteredDescriptors.TryGetValue(type, out descriptor))
|
||||
{
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
if (typeof (IDictionary).IsAssignableFrom(type))
|
||||
{
|
||||
// IDictionary
|
||||
descriptor = new DictionaryDescriptor(settings, type);
|
||||
}
|
||||
else if (typeof (ICollection).IsAssignableFrom(type))
|
||||
{
|
||||
// ICollection
|
||||
descriptor = new CollectionDescriptor(settings, type);
|
||||
}
|
||||
else if (type.IsArray)
|
||||
{
|
||||
// array[]
|
||||
descriptor = new ArrayDescriptor(settings, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
// standard object (class or value type)
|
||||
descriptor = new ObjectDescriptor(settings, type);
|
||||
}
|
||||
|
||||
// Register this descriptor
|
||||
RegisteredDescriptors.Add(type, descriptor);
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a descriptor for a <see cref="System.Collections.IDictionary"/>.
|
||||
/// </summary>
|
||||
public class DictionaryDescriptor : ObjectDescriptor
|
||||
{
|
||||
private readonly Type keyType;
|
||||
private readonly Type valueType;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DictionaryDescriptor" /> class.
|
||||
/// </summary>
|
||||
/// <param name="settings">The serializer settings.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
public DictionaryDescriptor(YamlSerializerSettings settings, Type type) : base(settings, type)
|
||||
{
|
||||
// extract Key, Value types from IDictionary<??, ??>
|
||||
var interfaceType = type.GetInterface(typeof(IDictionary<,>));
|
||||
if (interfaceType != null)
|
||||
{
|
||||
keyType = interfaceType.GetGenericArguments()[0];
|
||||
valueType = interfaceType.GetGenericArguments()[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
keyType = typeof(object);
|
||||
valueType = typeof(object);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the key.
|
||||
/// </summary>
|
||||
/// <value>The type of the key.</value>
|
||||
public Type KeyType
|
||||
{
|
||||
get { return keyType; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the value.
|
||||
/// </summary>
|
||||
/// <value>The type of the value.</value>
|
||||
public Type ValueType
|
||||
{
|
||||
get { return valueType; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the value passed is readonly.
|
||||
/// </summary>
|
||||
/// <param name="thisObject">The this object.</param>
|
||||
/// <returns><c>true</c> if [is read only] [the specified this object]; otherwise, <c>false</c>.</returns>
|
||||
public bool IsReadOnly(object thisObject)
|
||||
{
|
||||
return ((IDictionary)thisObject).IsReadOnly;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,15 +20,12 @@
|
|||
// SOFTWARE.
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using YamlDotNet;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// The exception that is thrown when a duplicate anchor is detected.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class DuplicateAnchorException : YamlException
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using YamlDotNet;
|
||||
using YamlDotNet.Events;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="IMemberDescriptor"/> for a <see cref="FieldInfo"/>
|
||||
/// </summary>
|
||||
public class FieldDescriptor : MemberDescriptorBase
|
||||
{
|
||||
private readonly FieldInfo fieldInfo;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FieldDescriptor"/> class.
|
||||
/// </summary>
|
||||
/// <param name="fieldInfo">The property information.</param>
|
||||
public FieldDescriptor(FieldInfo fieldInfo) : base(fieldInfo)
|
||||
{
|
||||
if (fieldInfo == null) throw new ArgumentNullException("fieldInfo");
|
||||
|
||||
this.fieldInfo = fieldInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the property information attached to this instance.
|
||||
/// </summary>
|
||||
/// <value>The property information.</value>
|
||||
public FieldInfo FieldInfo
|
||||
{
|
||||
get { return fieldInfo; }
|
||||
}
|
||||
|
||||
public override Type Type
|
||||
{
|
||||
get { return fieldInfo.FieldType; }
|
||||
}
|
||||
|
||||
public override object Get(object thisObject)
|
||||
{
|
||||
return fieldInfo.GetValue(thisObject);
|
||||
}
|
||||
|
||||
public override void Set(object thisObject, object value)
|
||||
{
|
||||
fieldInfo.SetValue(thisObject, value);
|
||||
}
|
||||
|
||||
public override bool HasSet
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("Field [{0}] from Type [{1}]", Name, FieldInfo.DeclaringType != null ? FieldInfo.DeclaringType.FullName : string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// A registry for all attributes.
|
||||
/// </summary>
|
||||
public interface IAttributeRegistry
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the attributes associated with the specified member.
|
||||
/// </summary>
|
||||
/// <param name="memberInfo">The reflection member.</param>
|
||||
/// <param name="inherit">if set to <c>true</c> includes inherited attributes.</param>
|
||||
/// <returns>An enumeration of <see cref="Attribute"/>.</returns>
|
||||
List<Attribute> GetAttributes(MemberInfo memberInfo, bool inherit = true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attributes associated with the specified member.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the attribute</typeparam>
|
||||
/// <param name="memberInfo">The member information.</param>
|
||||
/// <param name="inherit">if set to <c>true</c> [inherit].</param>
|
||||
/// <returns>An enumeration of <see cref="Attribute"/>.</returns>
|
||||
IEnumerable<T> GetAttributes<T>(MemberInfo memberInfo, bool inherit = true) where T : Attribute;
|
||||
|
||||
/// <summary>
|
||||
/// Gets an attribute associated with the specified member.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the attribute</typeparam>
|
||||
/// <param name="memberInfo">The member information.</param>
|
||||
/// <param name="inherit">if set to <c>true</c> [inherit].</param>
|
||||
/// <returns>An attribute of type {T} if it was found; otherwise <c>null</c> </returns>
|
||||
T GetAttribute<T>(MemberInfo memberInfo, bool inherit = true) where T : Attribute;
|
||||
|
||||
/// <summary>
|
||||
/// Registers an attribute for the specified member. Restriction: Attributes registered this way cannot be listed in inherited attributes.
|
||||
/// </summary>
|
||||
/// <param name="memberInfo">The member information.</param>
|
||||
/// <param name="attribute">The attribute.</param>
|
||||
void Register(MemberInfo memberInfo, Attribute attribute);
|
||||
}
|
||||
}
|
|
@ -1,12 +1,20 @@
|
|||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface used to write YAML events.
|
||||
/// </summary>
|
||||
public interface IEventEmitter
|
||||
{
|
||||
void Emit(AliasEventInfo eventInfo);
|
||||
|
||||
void Emit(ScalarEventInfo eventInfo);
|
||||
|
||||
void Emit(MappingStartEventInfo eventInfo);
|
||||
|
||||
void Emit(MappingEndEventInfo eventInfo);
|
||||
|
||||
void Emit(SequenceStartEventInfo eventInfo);
|
||||
|
||||
void Emit(SequenceEndEventInfo eventInfo);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Describe a member of an object.
|
||||
/// </summary>
|
||||
public interface IMemberDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type.
|
||||
/// </summary>
|
||||
/// <value>The type.</value>
|
||||
Type Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the mode of serialization for this member.
|
||||
/// </summary>
|
||||
/// <value>The mode.</value>
|
||||
SerializeMemberMode SerializeMemberMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of this memeber for the specified instance.
|
||||
/// </summary>
|
||||
/// <param name="thisObject">The this object to get the value from.</param>
|
||||
/// <returns>Value of the member.</returns>
|
||||
object Get(object thisObject);
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value of this memeber for the specified instance.
|
||||
/// </summary>
|
||||
/// <param name="thisObject">The this object.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
void Set(object thisObject, object value);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance has set method.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance has set method; otherwise, <c>false</c>.</value>
|
||||
bool HasSet { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this member should be serialized.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [should serialize]; otherwise, <c>false</c>.</value>
|
||||
Func<object, bool> ShouldSerialize { get; }
|
||||
}
|
||||
}
|
|
@ -1,22 +1,49 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to the properties of a type.
|
||||
/// Provides access members of a type.
|
||||
/// </summary>
|
||||
public interface ITypeDescriptor
|
||||
{
|
||||
IEnumerable<IPropertyDescriptor> GetProperties(Type type);
|
||||
/// <summary>
|
||||
/// Gets the type described by this instance.
|
||||
/// </summary>
|
||||
/// <value>The type.</value>
|
||||
Type Type { get; }
|
||||
|
||||
IPropertyDescriptor GetProperty(Type type, string name);
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the members of this type.
|
||||
/// </summary>
|
||||
/// <value>The members.</value>
|
||||
IEnumerable<IMemberDescriptor> Members { get; }
|
||||
|
||||
public interface IPropertyDescriptor
|
||||
{
|
||||
string Name { get; }
|
||||
PropertyInfo Property { get; }
|
||||
/// <summary>
|
||||
/// Gets the member count.
|
||||
/// </summary>
|
||||
/// <value>The member count.</value>
|
||||
int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance has members.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance has members; otherwise, <c>false</c>.</value>
|
||||
bool HasMembers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IMemberDescriptor"/> with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>The member.</returns>
|
||||
IMemberDescriptor this[string name] { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this instance contains a member with the specified member name.
|
||||
/// </summary>
|
||||
/// <param name="memberName">Name of the member.</param>
|
||||
/// <returns><c>true</c> if this instance contains a member with the specified member name; otherwise, <c>false</c>.</returns>
|
||||
bool Contains(string memberName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// A factory to create an instance of a <see cref="ITypeDescriptor"/>
|
||||
/// </summary>
|
||||
public interface ITypeDescriptorFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Tries to create an instance of a <see cref="ITypeDescriptor"/> from the type. Return null if this factory is not handling this type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>ITypeDescriptor.</returns>
|
||||
ITypeDescriptor Find(Type type);
|
||||
}
|
||||
}
|
|
@ -20,23 +20,29 @@
|
|||
// SOFTWARE.
|
||||
|
||||
using System;
|
||||
using YamlDotNet;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows an object to customize how it is serialized and deserialized.
|
||||
/// </summary>
|
||||
public interface IYamlSerializable
|
||||
public interface IYamlProcessor
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads this object's state from a YAML parser.
|
||||
/// </summary>
|
||||
void ReadYaml(IParser parser);
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="expectedType">Expected type. May be null.</param>
|
||||
/// <returns>A instance of the object deserialized from Yaml.</returns>
|
||||
object ReadYaml(SerializerContext context, object value, Type expectedType);
|
||||
|
||||
/// <summary>
|
||||
/// Writes this object's state to a YAML emitter.
|
||||
/// </summary>
|
||||
void WriteYaml(IEmitter emitter);
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
void WriteYaml(SerializerContext context, object value, Type type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// A factory of <see cref="IYamlProcessor"/>
|
||||
/// </summary>
|
||||
public interface IYamlSerializableFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Try to create a <see cref="IYamlProcessor"/> or return null if not supported for a particular .NET type.
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>If supported, return an instance of <see cref="IYamlProcessor"/> else return <c>null</c>.</returns>
|
||||
IYamlProcessor TryCreate(SerializerContext context, Type type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
internal class IdentityEqualityComparer<T> : IEqualityComparer<T> where T : class
|
||||
{
|
||||
public bool Equals(T left, T right)
|
||||
{
|
||||
return ReferenceEquals(left, right);
|
||||
}
|
||||
|
||||
public int GetHashCode(T value)
|
||||
{
|
||||
return RuntimeHelpers.GetHashCode(value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for <see cref="IMemberDescriptor"/> for a <see cref="MemberInfo"/>
|
||||
/// </summary>
|
||||
public abstract class MemberDescriptorBase : IMemberDescriptor
|
||||
{
|
||||
protected MemberDescriptorBase(MemberInfo memberInfo)
|
||||
{
|
||||
if (memberInfo == null) throw new ArgumentNullException("memberInfo");
|
||||
|
||||
MemberInfo = memberInfo;
|
||||
Name = MemberInfo.Name;
|
||||
}
|
||||
|
||||
public string Name { get; internal set; }
|
||||
public abstract Type Type { get; }
|
||||
public SerializeMemberMode SerializeMemberMode { get; internal set; }
|
||||
public abstract object Get(object thisObject);
|
||||
public abstract void Set(object thisObject, object value);
|
||||
public abstract bool HasSet { get; }
|
||||
public Func<object, bool> ShouldSerialize { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the member information.
|
||||
/// </summary>
|
||||
/// <value>The member information.</value>
|
||||
public MemberInfo MemberInfo { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of a <see cref="ITypeDescriptor"/>.
|
||||
/// </summary>
|
||||
public class ObjectDescriptor : ITypeDescriptor
|
||||
{
|
||||
private readonly static object[] EmptyObjectArray = new object[0];
|
||||
private readonly YamlSerializerSettings settings;
|
||||
private readonly Type type;
|
||||
private readonly IMemberDescriptor[] members;
|
||||
private readonly Dictionary<string, IMemberDescriptor> mapMembers;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ObjectDescriptor" /> class.
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <exception cref="YamlException">Failed to get ObjectDescriptor for type [{0}]. The member [{1}] cannot be registered as a member with the same name is already registered [{2}].DoFormat(type.FullName, member, existingMember)</exception>
|
||||
public ObjectDescriptor(YamlSerializerSettings settings, Type type)
|
||||
{
|
||||
if (settings == null) throw new ArgumentNullException("settings");
|
||||
if (type == null) throw new ArgumentNullException("type");
|
||||
|
||||
this.settings = settings;
|
||||
this.type = type;
|
||||
this.members = PrepareMembers().ToArray();
|
||||
|
||||
// If no members found, we don't need to build a dictionary map
|
||||
if (members.Length <= 0) return;
|
||||
|
||||
mapMembers = new Dictionary<string, IMemberDescriptor>(members.Length);
|
||||
foreach (var member in Members)
|
||||
{
|
||||
IMemberDescriptor existingMember;
|
||||
if (mapMembers.TryGetValue(member.Name, out existingMember))
|
||||
{
|
||||
throw new YamlException("Failed to get ObjectDescriptor for type [{0}]. The member [{1}] cannot be registered as a member with the same name is already registered [{2}]".DoFormat(type.FullName, member, existingMember));
|
||||
}
|
||||
|
||||
mapMembers.Add(member.Name, member);
|
||||
}
|
||||
}
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get { return type; }
|
||||
}
|
||||
|
||||
public IEnumerable<IMemberDescriptor> Members
|
||||
{
|
||||
get { return members; }
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return members.Length; }
|
||||
}
|
||||
|
||||
public bool HasMembers
|
||||
{
|
||||
get { return members.Length > 0; }
|
||||
}
|
||||
|
||||
public IMemberDescriptor this[string name]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (mapMembers == null) throw new KeyNotFoundException(name);
|
||||
return mapMembers[name];
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(string memberName)
|
||||
{
|
||||
return mapMembers != null && mapMembers.ContainsKey(memberName);
|
||||
}
|
||||
|
||||
protected YamlSerializerSettings Settings
|
||||
{
|
||||
get { return settings; }
|
||||
}
|
||||
|
||||
protected virtual List<IMemberDescriptor> PrepareMembers()
|
||||
{
|
||||
|
||||
// Add all public properties with a readable get method
|
||||
var memberList = (from propertyInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||||
where
|
||||
propertyInfo.CanRead && propertyInfo.GetGetMethod(false) != null &&
|
||||
propertyInfo.GetIndexParameters().Length == 0
|
||||
select new PropertyDescriptor(propertyInfo)
|
||||
into member
|
||||
where PrepareMember(member)
|
||||
select member).Cast<IMemberDescriptor>().ToList();
|
||||
|
||||
// Add all public fields
|
||||
memberList.AddRange((from fieldInfo in type.GetFields(BindingFlags.Instance | BindingFlags.Public)
|
||||
where fieldInfo.IsPublic
|
||||
select new FieldDescriptor(fieldInfo)
|
||||
into member where PrepareMember(member) select member));
|
||||
|
||||
return memberList;
|
||||
}
|
||||
|
||||
private bool PrepareMember(MemberDescriptorBase member)
|
||||
{
|
||||
// If the member has a set, this is a conventional assign method
|
||||
if (member.HasSet)
|
||||
{
|
||||
member.SerializeMemberMode = SerializeMemberMode.Assign;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else we cannot only assign its content if it is a class
|
||||
member.SerializeMemberMode = type.IsClass ? SerializeMemberMode.Content : SerializeMemberMode.Never;
|
||||
}
|
||||
|
||||
var attributeRegistry = Settings.AttributeRegistry;
|
||||
|
||||
// Member is not displayed if there is a YamlIgnore attribute on it
|
||||
if (attributeRegistry.GetAttribute<YamlIgnoreAttribute>(member.MemberInfo, false) != null)
|
||||
return false;
|
||||
|
||||
var memberAttribute = attributeRegistry.GetAttribute<YamlMemberAttribute>(member.MemberInfo, false);
|
||||
if (memberAttribute != null)
|
||||
{
|
||||
if (!member.HasSet)
|
||||
{
|
||||
if (memberAttribute.SerializeMethod == SerializeMemberMode.Assign ||
|
||||
(type.IsValueType && member.SerializeMemberMode == SerializeMemberMode.Content))
|
||||
throw new ArgumentException("{0} {1} is not writeable by {2}.".DoFormat(type.FullName, member.Name, memberAttribute.SerializeMethod.ToString()));
|
||||
}
|
||||
member.SerializeMemberMode = memberAttribute.SerializeMethod;
|
||||
}
|
||||
|
||||
if (member.SerializeMemberMode == SerializeMemberMode.Binary)
|
||||
{
|
||||
if (!type.IsArray)
|
||||
throw new InvalidOperationException("{0} {1} of {2} is not an array. Can not be serialized as binary."
|
||||
.DoFormat(type.FullName, member.Name, type.FullName));
|
||||
if (!type.GetElementType().IsPureValueType())
|
||||
throw new InvalidOperationException("{0} is not a pure ValueType. {1} {2} of {3} can not serialize as binary.".DoFormat(type.GetElementType(), type.FullName, member.Name, type.FullName));
|
||||
}
|
||||
|
||||
// ShouldSerialize
|
||||
// YamlSerializeAttribute(Never) => false
|
||||
// ShouldSerializeSomeProperty => call it
|
||||
// DefaultValueAttribute(default) => compare to it
|
||||
// otherwise => true
|
||||
var shouldSerialize = type.GetMethod("ShouldSerialize" + member.Name, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (shouldSerialize != null && shouldSerialize.ReturnType == typeof(bool) && member.ShouldSerialize == null)
|
||||
member.ShouldSerialize = obj => (bool)shouldSerialize.Invoke(obj, EmptyObjectArray);
|
||||
|
||||
|
||||
var defaultValueAttribute = attributeRegistry.GetAttribute<DefaultValueAttribute>(member.MemberInfo);
|
||||
if (defaultValueAttribute != null && member.ShouldSerialize == null)
|
||||
{
|
||||
object defaultValue = defaultValueAttribute.Value;
|
||||
Type defaultType = defaultValue == null ? null : defaultValue.GetType();
|
||||
if (defaultType.IsNumeric() && defaultType != type)
|
||||
defaultValue = type.CastToNumericType(defaultValue);
|
||||
member.ShouldSerialize = obj => !TypeExtensions.AreEqual(defaultValue, member.Get(obj));
|
||||
}
|
||||
|
||||
if (member.ShouldSerialize == null)
|
||||
member.ShouldSerialize = obj => true;
|
||||
|
||||
if (memberAttribute != null && !string.IsNullOrEmpty(memberAttribute.Name))
|
||||
{
|
||||
member.Name = memberAttribute.Name;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using YamlDotNet.Events;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
internal class AnchorProcessor : ChainedProcessor
|
||||
{
|
||||
private Dictionary<string, object> aliasToObject;
|
||||
private Dictionary<object, string> objectToAlias;
|
||||
|
||||
public AnchorProcessor(IYamlProcessor next) : base(next)
|
||||
{
|
||||
}
|
||||
|
||||
public override object ReadYaml(SerializerContext context, object value, Type expectedType)
|
||||
{
|
||||
var reader = context.Reader;
|
||||
|
||||
// Process Anchor alias (*oxxx)
|
||||
var alias = reader.Allow<AnchorAlias>();
|
||||
if (alias != null)
|
||||
{
|
||||
if (!AliasToObject.TryGetValue(alias.Value, out value))
|
||||
{
|
||||
throw new YamlException("Alias [{0}] not found".DoFormat(alias.Value));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// Test if current node as an anchor
|
||||
string anchor = null;
|
||||
var nodeEvent = reader.Peek<NodeEvent>();
|
||||
if (nodeEvent != null && !string.IsNullOrEmpty(nodeEvent.Anchor))
|
||||
{
|
||||
anchor = nodeEvent.Anchor;
|
||||
}
|
||||
|
||||
// Deserialize the current node
|
||||
value = base.ReadYaml(context, value, expectedType);
|
||||
|
||||
// Store Anchor (&oxxx) and override any defined anchor
|
||||
if (anchor != null)
|
||||
{
|
||||
AliasToObject[anchor] = value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public override void WriteYaml(SerializerContext context, object value, Type type)
|
||||
{
|
||||
if (value != null && Type.GetTypeCode(value.GetType()) == TypeCode.Object)
|
||||
{
|
||||
string alias;
|
||||
if (ObjectToString.TryGetValue(value, out alias))
|
||||
{
|
||||
context.Writer.Emit(new AliasEventInfo(value, type) {Alias = alias});
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias = string.Format("o{0}", context.AnchorCount);
|
||||
ObjectToString.Add(value, alias);
|
||||
|
||||
// Store the alias in the context
|
||||
context.Anchors.Push(alias);
|
||||
context.AnchorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
base.WriteYaml(context, value, type);
|
||||
}
|
||||
|
||||
private Dictionary<string, object> AliasToObject
|
||||
{
|
||||
get { return aliasToObject ?? (aliasToObject = new Dictionary<string, object>()); }
|
||||
}
|
||||
|
||||
private Dictionary<object, string> ObjectToString
|
||||
{
|
||||
get { return objectToAlias ?? (objectToAlias = new Dictionary<object, string>(new IdentityEqualityComparer<object>())); }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
internal class ChainedProcessor : IYamlProcessor
|
||||
{
|
||||
private readonly IYamlProcessor next;
|
||||
|
||||
public ChainedProcessor(IYamlProcessor next)
|
||||
{
|
||||
if (next == null) throw new ArgumentNullException("next");
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
public virtual object ReadYaml(SerializerContext context, object value, Type expectedType)
|
||||
{
|
||||
return next.ReadYaml(context, value, expectedType);
|
||||
}
|
||||
|
||||
public virtual void WriteYaml(SerializerContext context, object value, Type type)
|
||||
{
|
||||
next.WriteYaml(context, value, type);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using YamlDotNet.Events;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
internal class DictionaryProcessor : ObjectProcessor
|
||||
{
|
||||
private readonly PureDictionaryProcessor pureDictionaryProcessor;
|
||||
|
||||
public DictionaryProcessor(YamlSerializerSettings settings) : base(settings)
|
||||
{
|
||||
pureDictionaryProcessor = new PureDictionaryProcessor(settings);
|
||||
}
|
||||
|
||||
protected override void ReadItem(SerializerContext context, object thisObject, ITypeDescriptor typeDescriptor)
|
||||
{
|
||||
var dictionary = (IDictionary) thisObject;
|
||||
var dictionaryDescriptor = (DictionaryDescriptor) typeDescriptor;
|
||||
|
||||
if (!dictionaryDescriptor.HasMembers)
|
||||
{
|
||||
var key = context.ReadYaml(null, dictionaryDescriptor.KeyType);
|
||||
var value = context.ReadYaml(null, dictionaryDescriptor.ValueType);
|
||||
dictionary.Add(key, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
var keyEvent = context.Reader.Peek<Scalar>();
|
||||
if (keyEvent != null)
|
||||
{
|
||||
if (keyEvent.Value == Settings.PrefixForItems)
|
||||
{
|
||||
pureDictionaryProcessor.ReadYaml(context, thisObject, thisObject.GetType());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
base.ReadItem(context, thisObject, typeDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteItems(SerializerContext context, object thisObject, ITypeDescriptor typeDescriptor)
|
||||
{
|
||||
if (!typeDescriptor.HasMembers)
|
||||
{
|
||||
pureDictionaryProcessor.WriteItems(context, thisObject, typeDescriptor);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Serialize Dictionary members
|
||||
foreach (var member in typeDescriptor.Members)
|
||||
{
|
||||
// Emit the key name
|
||||
context.Writer.Emit(new ScalarEventInfo(member.Name, typeof(string)));
|
||||
|
||||
var memberValue = member.Get(thisObject);
|
||||
var memberType = member.Type;
|
||||
context.WriteYaml(memberValue, memberType);
|
||||
}
|
||||
|
||||
context.Writer.Emit(new ScalarEventInfo(Settings.PrefixForItems, typeof(string)));
|
||||
pureDictionaryProcessor.WriteYaml(context, thisObject, thisObject.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
internal class PureDictionaryProcessor : ObjectProcessor
|
||||
{
|
||||
public PureDictionaryProcessor(YamlSerializerSettings settings) : base(settings)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ReadItem(SerializerContext context, object thisObject, ITypeDescriptor typeDescriptor)
|
||||
{
|
||||
var dictionary = (IDictionary)thisObject;
|
||||
var dictionaryDescriptor = (DictionaryDescriptor)typeDescriptor;
|
||||
|
||||
var key = context.ReadYaml(null, dictionaryDescriptor.KeyType);
|
||||
var value = context.ReadYaml(null, dictionaryDescriptor.ValueType);
|
||||
dictionary.Add(key, value);
|
||||
}
|
||||
|
||||
public override void WriteItems(SerializerContext context, object thisObject, ITypeDescriptor typeDescriptor)
|
||||
{
|
||||
var dictionary = (IDictionary) thisObject;
|
||||
var dictionaryDescriptor = (DictionaryDescriptor)typeDescriptor;
|
||||
|
||||
var keys = dictionary.Keys;
|
||||
if (context.Settings.SortKeyForMapping)
|
||||
{
|
||||
var sortedKeys = keys.Cast<object>().ToList();
|
||||
sortedKeys.Sort((left, right) =>
|
||||
{
|
||||
if (left is IComparable && right is IComparable)
|
||||
{
|
||||
return ((IComparable) left).CompareTo(right);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
keys = sortedKeys;
|
||||
}
|
||||
|
||||
var keyType = dictionaryDescriptor.KeyType;
|
||||
var valueType = dictionaryDescriptor.ValueType;
|
||||
foreach (var key in keys)
|
||||
{
|
||||
context.WriteYaml(key, keyType);
|
||||
context.WriteYaml(dictionary[key], valueType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
using System;
|
||||
using YamlDotNet.Events;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
public class ObjectProcessor : IYamlProcessor
|
||||
{
|
||||
private readonly YamlSerializerSettings settings;
|
||||
|
||||
public ObjectProcessor(YamlSerializerSettings settings)
|
||||
{
|
||||
if (settings == null) throw new ArgumentNullException("settings");
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public YamlSerializerSettings Settings
|
||||
{
|
||||
get { return settings; }
|
||||
}
|
||||
|
||||
protected virtual bool IsSequence(ITypeDescriptor typeDescriptor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual object ReadYaml(SerializerContext context, object value, Type expectedType)
|
||||
{
|
||||
var reader = context.Reader;
|
||||
var nodeEvent = reader.Peek<NodeEvent>();
|
||||
|
||||
var type = context.TypeFromTag(nodeEvent.Tag) ?? (value != null ? value.GetType() : expectedType);
|
||||
if (type == null)
|
||||
{
|
||||
throw new YamlException("Unable to find type for mapping [{0}]".DoFormat(nodeEvent));
|
||||
}
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
value = context.CreateType(type);
|
||||
if (value == null)
|
||||
{
|
||||
throw new YamlException("Unexpected null value");
|
||||
}
|
||||
}
|
||||
|
||||
// Get the object accessor for the corresponding class
|
||||
var typeDescriptor = context.TypeDescriptorFactory.Find(value.GetType());
|
||||
var isSequence = IsSequence(typeDescriptor);
|
||||
|
||||
if (isSequence)
|
||||
{
|
||||
ReadItems<SequenceStart,SequenceEnd>(context, value, typeDescriptor);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadItems<MappingStart, MappingEnd>(context, value, typeDescriptor);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected virtual void ReadItems<TStart, TEnd>(SerializerContext context, object thisObject, ITypeDescriptor typeDescriptor)
|
||||
where TStart : NodeEvent
|
||||
where TEnd : ParsingEvent
|
||||
{
|
||||
var reader = context.Reader;
|
||||
reader.Expect<TStart>();
|
||||
while (!reader.Accept<TEnd>())
|
||||
{
|
||||
ReadItem(context, thisObject, typeDescriptor);
|
||||
}
|
||||
reader.Expect<TEnd>();
|
||||
}
|
||||
|
||||
protected virtual void ReadItem(SerializerContext context, object thisObject, ITypeDescriptor typeDescriptor)
|
||||
{
|
||||
var reader = context.Reader;
|
||||
|
||||
// For a regular object, the key is expected to be a simple scalar
|
||||
var propertyName = reader.Expect<Scalar>().Value;
|
||||
var memberAccessor = typeDescriptor[propertyName];
|
||||
|
||||
// Read the value according to the type
|
||||
var propertyType = memberAccessor.Type;
|
||||
|
||||
object value = null;
|
||||
if (memberAccessor.SerializeMemberMode == SerializeMemberMode.Content)
|
||||
{
|
||||
value = memberAccessor.Get(thisObject);
|
||||
}
|
||||
|
||||
var propertyValue = context.ReadYaml(value, propertyType);
|
||||
|
||||
if (memberAccessor.HasSet && memberAccessor.SerializeMemberMode != SerializeMemberMode.Content)
|
||||
{
|
||||
memberAccessor.Set(thisObject, propertyValue);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void WriteYaml(SerializerContext context, object value, Type type)
|
||||
{
|
||||
var typeOfValue = value.GetType();
|
||||
var tag = typeOfValue == type ? null : context.TagFromType(typeOfValue);
|
||||
|
||||
// Get the object accessor for the corresponding class
|
||||
var typeDescriptor = context.TypeDescriptorFactory.Find(typeOfValue);
|
||||
|
||||
var isSequence = IsSequence(typeDescriptor);
|
||||
|
||||
if (isSequence)
|
||||
{
|
||||
context.Writer.Emit(new SequenceStartEventInfo(value, typeOfValue) { Tag = tag });
|
||||
WriteItems(context, value, typeDescriptor);
|
||||
context.Writer.Emit(new SequenceEndEventInfo(value, typeOfValue));
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Writer.Emit(new MappingStartEventInfo(value, typeOfValue) { Tag = tag });
|
||||
WriteItems(context, value, typeDescriptor);
|
||||
context.Writer.Emit(new MappingEndEventInfo(value, typeOfValue));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void WriteItems(SerializerContext context, object thisObject, ITypeDescriptor typeDescriptor)
|
||||
{
|
||||
foreach (var member in typeDescriptor.Members)
|
||||
{
|
||||
// Skip any member that we won't serialize
|
||||
if (!member.ShouldSerialize(thisObject)) continue;
|
||||
|
||||
// Emit the key name
|
||||
context.Writer.Emit(new ScalarEventInfo(member.Name, typeof (string)));
|
||||
|
||||
var memberValue = member.Get(thisObject);
|
||||
var memberType = member.Type;
|
||||
context.WriteYaml(memberValue, memberType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,26 +3,69 @@ using System.Reflection;
|
|||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
public sealed class PropertyDescriptor : IPropertyDescriptor
|
||||
/// <summary>
|
||||
/// A <see cref="IMemberDescriptor"/> for a <see cref="PropertyInfo"/>
|
||||
/// </summary>
|
||||
public class PropertyDescriptor : MemberDescriptorBase
|
||||
{
|
||||
public PropertyDescriptor(PropertyInfo property, string name)
|
||||
private readonly PropertyInfo propertyInfo;
|
||||
private readonly MethodInfo getMethod;
|
||||
private readonly MethodInfo setMethod;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PropertyDescriptor"/> class.
|
||||
/// </summary>
|
||||
/// <param name="propertyInfo">The property information.</param>
|
||||
public PropertyDescriptor(PropertyInfo propertyInfo) : base(propertyInfo)
|
||||
{
|
||||
if (property == null)
|
||||
if (propertyInfo == null) throw new ArgumentNullException("propertyInfo");
|
||||
|
||||
this.propertyInfo = propertyInfo;
|
||||
|
||||
getMethod = propertyInfo.GetGetMethod(false);
|
||||
if (propertyInfo.CanWrite && propertyInfo.GetSetMethod(false) != null)
|
||||
{
|
||||
throw new ArgumentNullException("property");
|
||||
setMethod = propertyInfo.GetSetMethod(false);
|
||||
}
|
||||
|
||||
Property = property;
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
throw new ArgumentNullException("name");
|
||||
}
|
||||
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public PropertyInfo Property { get; private set; }
|
||||
public string Name { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the property information attached to this instance.
|
||||
/// </summary>
|
||||
/// <value>The property information.</value>
|
||||
public PropertyInfo PropertyInfo
|
||||
{
|
||||
get { return propertyInfo; }
|
||||
}
|
||||
|
||||
public override Type Type
|
||||
{
|
||||
get { return propertyInfo.PropertyType; }
|
||||
}
|
||||
|
||||
public override object Get(object thisObject)
|
||||
{
|
||||
return getMethod.Invoke(thisObject, null);
|
||||
}
|
||||
|
||||
public override void Set(object thisObject, object value)
|
||||
{
|
||||
if (HasSet)
|
||||
setMethod.Invoke(thisObject, new [] {value});
|
||||
}
|
||||
|
||||
public override bool HasSet
|
||||
{
|
||||
get { return setMethod != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("Property [{0}] from Type [{1}]", Name, PropertyInfo.DeclaringType != null ? PropertyInfo.DeclaringType.FullName : string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A context used while deserializing.
|
||||
/// </summary>
|
||||
public class SerializerContext
|
||||
{
|
||||
private readonly YamlSerializerSettings settings;
|
||||
private readonly TagRegistry tagRegistry;
|
||||
private readonly ITypeDescriptorFactory typeDescriptorFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SerializerContext"/> class.
|
||||
/// </summary>
|
||||
/// <param name="serializer">The serializer.</param>
|
||||
internal SerializerContext(YamlSerializer serializer)
|
||||
{
|
||||
Serializer = serializer;
|
||||
settings = serializer.Settings;
|
||||
tagRegistry = serializer.TagRegistry;
|
||||
typeDescriptorFactory = settings.TypeDescriptorFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether we are in the context of serializing.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if we are in the context of serializing; otherwise, <c>false</c>.</value>
|
||||
public bool IsSerializing
|
||||
{
|
||||
get { return Writer != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the settings.
|
||||
/// </summary>
|
||||
/// <value>The settings.</value>
|
||||
public YamlSerializerSettings Settings
|
||||
{
|
||||
get { return settings; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type descriptor factory.
|
||||
/// </summary>
|
||||
/// <value>The type descriptor factory.</value>
|
||||
public ITypeDescriptorFactory TypeDescriptorFactory
|
||||
{
|
||||
get { return typeDescriptorFactory; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the serializer.
|
||||
/// </summary>
|
||||
/// <value>The serializer.</value>
|
||||
public YamlSerializer Serializer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reader used while deserializing.
|
||||
/// </summary>
|
||||
/// <value>The reader.</value>
|
||||
public EventReader Reader { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The default function to read a Yaml.
|
||||
/// </summary>
|
||||
public Func<object, Type, object> ReadYaml { get; set; }
|
||||
|
||||
public Func<Type, object> CreateType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the writer used while deserializing.
|
||||
/// </summary>
|
||||
/// <value>The writer.</value>
|
||||
public IEventEmitter Writer { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The default function to write an object to Yaml
|
||||
/// </summary>
|
||||
public Action<object, Type> WriteYaml { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resolves a type from the specified tag.
|
||||
/// </summary>
|
||||
/// <param name="tagName">Name of the tag.</param>
|
||||
/// <returns>Type.</returns>
|
||||
public Type TypeFromTag(string tagName)
|
||||
{
|
||||
return tagRegistry.TypeFromTag(tagName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves a tag from a type
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <returns>The associated tag</returns>
|
||||
public string TagFromType(Type type)
|
||||
{
|
||||
return tagRegistry.TagFromType(type);
|
||||
}
|
||||
|
||||
internal string GetAnchor()
|
||||
{
|
||||
return Anchors.Count > 0 ? Anchors.Pop() : null;
|
||||
}
|
||||
|
||||
internal Stack<string> Anchors = new Stack<string>();
|
||||
|
||||
internal int AnchorCount;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
internal class TagRegistry
|
||||
{
|
||||
private readonly Dictionary<string, Type> tagToType;
|
||||
private readonly Dictionary<Type, string> typeToTag;
|
||||
private readonly List<Assembly> lookupAssemblies;
|
||||
|
||||
public TagRegistry(YamlSerializerSettings settings)
|
||||
{
|
||||
tagToType = new Dictionary<string, Type>(settings.TagToType);
|
||||
typeToTag = new Dictionary<Type, string>(settings.TypeToTag);
|
||||
lookupAssemblies = new List<Assembly>(settings.LookupAssemblies);
|
||||
}
|
||||
|
||||
public Type TypeFromTag(string tagName)
|
||||
{
|
||||
if (tagName == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Type type;
|
||||
if (tagToType.TryGetValue(tagName, out type))
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
type = Type.GetType(tagName);
|
||||
if (type == null)
|
||||
{
|
||||
foreach (var assembly in lookupAssemblies)
|
||||
{
|
||||
type = assembly.GetType(tagName);
|
||||
if (type != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public string TagFromType(Type type)
|
||||
{
|
||||
string tagName;
|
||||
if (!typeToTag.TryGetValue(type, out tagName))
|
||||
{
|
||||
return string.Format("!{0}", type.FullName);
|
||||
}
|
||||
return tagName;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,10 +6,12 @@ namespace YamlDotNet.Serialization
|
|||
public sealed class WriterEventEmitter : IEventEmitter
|
||||
{
|
||||
private readonly IEmitter emitter;
|
||||
private readonly SerializerContext context;
|
||||
|
||||
public WriterEventEmitter(IEmitter emitter)
|
||||
public WriterEventEmitter(IEmitter emitter, SerializerContext context)
|
||||
{
|
||||
this.emitter = emitter;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
void IEventEmitter.Emit(AliasEventInfo eventInfo)
|
||||
|
@ -19,12 +21,12 @@ namespace YamlDotNet.Serialization
|
|||
|
||||
void IEventEmitter.Emit(ScalarEventInfo eventInfo)
|
||||
{
|
||||
emitter.Emit(new Scalar(eventInfo.Anchor, eventInfo.Tag, eventInfo.RenderedValue, eventInfo.Style, eventInfo.IsPlainImplicit, eventInfo.IsQuotedImplicit));
|
||||
emitter.Emit(new Scalar(eventInfo.Anchor ?? context.GetAnchor(), eventInfo.Tag, eventInfo.RenderedValue, eventInfo.Style, eventInfo.IsPlainImplicit, eventInfo.IsQuotedImplicit));
|
||||
}
|
||||
|
||||
void IEventEmitter.Emit(MappingStartEventInfo eventInfo)
|
||||
{
|
||||
emitter.Emit(new MappingStart(eventInfo.Anchor, eventInfo.Tag, eventInfo.IsImplicit, eventInfo.Style));
|
||||
emitter.Emit(new MappingStart(eventInfo.Anchor ?? context.GetAnchor(), eventInfo.Tag, eventInfo.IsImplicit, eventInfo.Style));
|
||||
}
|
||||
|
||||
void IEventEmitter.Emit(MappingEndEventInfo eventInfo)
|
||||
|
@ -34,7 +36,7 @@ namespace YamlDotNet.Serialization
|
|||
|
||||
void IEventEmitter.Emit(SequenceStartEventInfo eventInfo)
|
||||
{
|
||||
emitter.Emit(new SequenceStart(eventInfo.Anchor, eventInfo.Tag, eventInfo.IsImplicit, eventInfo.Style));
|
||||
emitter.Emit(new SequenceStart(eventInfo.Anchor ?? context.GetAnchor(), eventInfo.Tag, eventInfo.IsImplicit, eventInfo.Style));
|
||||
}
|
||||
|
||||
void IEventEmitter.Emit(SequenceEndEventInfo eventInfo)
|
||||
|
|
|
@ -2,12 +2,12 @@ using System;
|
|||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Instructs the YamlSerializer not to serialize the public field or public read/write property value.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
|
||||
public sealed class YamlIgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Instructs the YamlSerializer not to serialize the public field or public read/write property value.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
|
||||
public sealed class YamlIgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Specify the way to store a property or field of some class or structure.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public sealed class YamlMemberAttribute : Attribute
|
||||
{
|
||||
private readonly SerializeMemberMode serializeMethod;
|
||||
private readonly string name;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="YamlMemberAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
public YamlMemberAttribute(string name)
|
||||
{
|
||||
this.name = name;
|
||||
serializeMethod = SerializeMemberMode.Assign;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Specify the way to store a property or field of some class or structure.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="serializeMethod">The serialize method.</param>
|
||||
public YamlMemberAttribute(string name, SerializeMemberMode serializeMethod)
|
||||
{
|
||||
this.name = name;
|
||||
this.serializeMethod = serializeMethod;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify the way to store a property or field of some class or structure.
|
||||
/// </summary>
|
||||
/// <param name="serializeMethod">The serialize method.</param>
|
||||
public YamlMemberAttribute(SerializeMemberMode serializeMethod)
|
||||
{
|
||||
this.serializeMethod = serializeMethod;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
public string Name
|
||||
{
|
||||
get { return name; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the serialize method1.
|
||||
/// </summary>
|
||||
/// <value>The serialize method1.</value>
|
||||
public SerializeMemberMode SerializeMethod
|
||||
{
|
||||
get { return serializeMethod; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>Specify the way to store a property or field of some class or structure.</para>
|
||||
/// <para>See <see cref="Serializer"/> for detail.</para>
|
||||
/// </summary>
|
||||
public enum SerializeMemberMode
|
||||
{
|
||||
/// <summary>
|
||||
/// The property / field will not be stored.
|
||||
/// </summary>
|
||||
Never,
|
||||
|
||||
/// <summary>
|
||||
/// When restored, new object is created by using the parameters in
|
||||
/// the YAML data and assigned to the property / field. When the
|
||||
/// property / filed is writeable, this is the default.
|
||||
/// </summary>
|
||||
Assign,
|
||||
|
||||
/// <summary>
|
||||
/// Only valid for a property / field that has a class or struct type.
|
||||
/// When restored, instead of recreating the whole class or struct,
|
||||
/// the members are independently restored. When the property / field
|
||||
/// is not writeable this is the default.
|
||||
/// </summary>
|
||||
Content,
|
||||
|
||||
/// <summary>
|
||||
/// Only valid for a property / field that has an array type of a
|
||||
/// some value type. The content of the array is stored in a binary
|
||||
/// format encoded in base64 style.
|
||||
/// </summary>
|
||||
Binary
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
using System.IO;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
public class YamlSerializer
|
||||
{
|
||||
private readonly YamlSerializerSettings settings;
|
||||
internal readonly TagRegistry TagRegistry;
|
||||
|
||||
public YamlSerializer() : this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public YamlSerializerSettings Settings { get { return settings; } }
|
||||
|
||||
public YamlSerializer(YamlSerializerSettings settings)
|
||||
{
|
||||
this.settings = settings ?? new YamlSerializerSettings();
|
||||
TagRegistry = new TagRegistry(Settings);
|
||||
}
|
||||
|
||||
public void Serialize(Stream stream, object value)
|
||||
{
|
||||
var context = new SerializerContext(this);
|
||||
var writer = CreateEmitter(stream, context);
|
||||
context.Writer = writer;
|
||||
|
||||
}
|
||||
|
||||
private IEventEmitter CreateEmitter(Stream stream, SerializerContext context)
|
||||
{
|
||||
return CreateEmitter(new Emitter(new StreamWriter(stream)), context);
|
||||
}
|
||||
|
||||
private IEventEmitter CreateEmitter(IEmitter emitter, SerializerContext context)
|
||||
{
|
||||
var writer = new WriterEventEmitter(emitter, context);
|
||||
|
||||
if (settings.EmitJsonComptible)
|
||||
{
|
||||
return new JsonEventEmitter(writer);
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Settings used to configure serialization.
|
||||
/// </summary>
|
||||
public class YamlSerializerSettings
|
||||
{
|
||||
internal readonly Dictionary<string, Type> TagToType = new Dictionary<string, Type>();
|
||||
internal readonly Dictionary<Type, string> TypeToTag = new Dictionary<Type, string>();
|
||||
private IAttributeRegistry attributeRegistry;
|
||||
private ITypeDescriptorFactory typeDescriptorFactory;
|
||||
private string prefixForItems;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="YamlSerializerSettings"/> class.
|
||||
/// </summary>
|
||||
public YamlSerializerSettings()
|
||||
{
|
||||
SortKeyForMapping = true;
|
||||
EmitJsonComptible = false;
|
||||
EmitCapacityForList = false;
|
||||
PrefixForItems = "~Items";
|
||||
AttributeRegistry = new DefaultAttributeRegistry();
|
||||
TypeDescriptorFactory = new DefaultDescriptorFactory(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to enable sorting keys for YAML mapping. Default is true. See remarks.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> to enable sorting keys for YAML mapping; otherwise, <c>false</c>.</value>
|
||||
/// <remarks>
|
||||
/// When storing a YAML document, It can be important to keep the same order for key mapping in order to keep
|
||||
/// a YAML document versionable/diffable.
|
||||
/// </remarks>
|
||||
public bool SortKeyForMapping { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to emit json comptible YAML.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if to emit json comptible YAML; otherwise, <c>false</c>.</value>
|
||||
public bool EmitJsonComptible { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the property <see cref="System.Collections.IList.Capacity"/> should be emitted. Default is false.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if the property <see cref="System.Collections.IList.Capacity"/> should be emitted; otherwise, <c>false</c>.</value>
|
||||
public bool EmitCapacityForList { get; set; }
|
||||
|
||||
public string PrefixForItems
|
||||
{
|
||||
get { return prefixForItems; }
|
||||
set
|
||||
{
|
||||
// TODO check prefix for items
|
||||
prefixForItems = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the attribute registry.
|
||||
/// </summary>
|
||||
/// <value>The attribute registry.</value>
|
||||
public IAttributeRegistry AttributeRegistry
|
||||
{
|
||||
get { return attributeRegistry; }
|
||||
set
|
||||
{
|
||||
if (value == null) throw new ArgumentNullException("value");
|
||||
attributeRegistry = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type descriptor factory used when trying to find a <see cref="ITypeDescriptor"/>.
|
||||
/// </summary>
|
||||
/// <value>The type descriptor factory.</value>
|
||||
/// <exception cref="System.ArgumentNullException">value</exception>
|
||||
public ITypeDescriptorFactory TypeDescriptorFactory
|
||||
{
|
||||
get { return typeDescriptorFactory; }
|
||||
set
|
||||
{
|
||||
if (value == null) throw new ArgumentNullException("value");
|
||||
typeDescriptorFactory = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterTagAlias(string tagName, Type type)
|
||||
{
|
||||
TagToType[tagName] = type;
|
||||
TypeToTag[type] = tagName;
|
||||
}
|
||||
|
||||
public List<Assembly> LookupAssemblies { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
|
||||
namespace YamlDotNet.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// An attribute to associate a tag with a particular type.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Enum)]
|
||||
public class YamlTagAttribute : Attribute
|
||||
{
|
||||
private readonly string tag;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="YamlTagAttribute"/> class.
|
||||
/// </summary>
|
||||
/// <param name="tag">The tag.</param>
|
||||
public YamlTagAttribute(string tag)
|
||||
{
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the tag.
|
||||
/// </summary>
|
||||
/// <value>The tag.</value>
|
||||
public string Tag { get { return tag; } }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
namespace YamlDotNet
|
||||
{
|
||||
/// <summary>
|
||||
/// Add extensions methods to <see cref="System.String"/>.
|
||||
/// </summary>
|
||||
internal static class StringExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Expression of string.Format(this, arg1, arg2, ...)
|
||||
/// </summary>
|
||||
/// <param name="format">The format string.</param>
|
||||
/// <param name="args">The arguments.</param>
|
||||
/// <returns>A formatted string.</returns>
|
||||
/// <see cref="string.Format(System.IFormatProvider,string,object[])"/>
|
||||
public static string DoFormat(this string format, params object[] args)
|
||||
{
|
||||
return string.Format(format, args);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace YamlDotNet
|
||||
{
|
||||
internal static class TypeExtensions
|
||||
{
|
||||
public static Type GetInterface(this Type type, Type lookInterfaceType)
|
||||
{
|
||||
if (lookInterfaceType.IsGenericTypeDefinition)
|
||||
{
|
||||
foreach (var interfaceType in type.GetInterfaces())
|
||||
{
|
||||
if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == lookInterfaceType)
|
||||
{
|
||||
return interfaceType;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var interfaceType in type.GetInterfaces())
|
||||
{
|
||||
if (interfaceType == lookInterfaceType)
|
||||
{
|
||||
return interfaceType;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the type is a ValueType and does not contain any non ValueType members.
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsPureValueType(this Type type)
|
||||
{
|
||||
if (type == null)
|
||||
return false;
|
||||
if (type == typeof(IntPtr))
|
||||
return false;
|
||||
if (type.IsPrimitive)
|
||||
return true;
|
||||
if (type.IsEnum)
|
||||
return true;
|
||||
if (!type.IsValueType)
|
||||
return false;
|
||||
// struct
|
||||
foreach (var f in type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance))
|
||||
if (!IsPureValueType(f.FieldType))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returnes true if the specified <paramref name="type"/> is a struct type.
|
||||
/// </summary>
|
||||
/// <param name="type"><see cref="Type"/> to be analyzed.</param>
|
||||
/// <returns>true if the specified <paramref name="type"/> is a struct type; otehrwise false.</returns>
|
||||
public static bool IsStruct(this Type type)
|
||||
{
|
||||
return type != null && type.IsValueType && !type.IsPrimitive;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return if an object is a numeric value.
|
||||
/// </summary>
|
||||
/// <param name="obj">Any object to be tested.</param>
|
||||
/// <returns>True if object is a numeric value.</returns>
|
||||
public static bool IsNumeric(this Type type)
|
||||
{
|
||||
return type != null && (type == typeof(sbyte) || type == typeof(short) || type == typeof(int) || type == typeof(long) ||
|
||||
type == typeof(byte) || type == typeof(ushort) || type == typeof(uint) || type == typeof(ulong) ||
|
||||
type == typeof(float) || type == typeof(double) || type == typeof(decimal));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two objects to see if they are equal or not. Null is acceptable.
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns></returns>
|
||||
public static bool AreEqual(object a, object b)
|
||||
{
|
||||
if (a == null)
|
||||
return b == null;
|
||||
if (b == null)
|
||||
return false;
|
||||
return a.Equals(b) || b.Equals(a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cast an object to a specified numeric type.
|
||||
/// </summary>
|
||||
/// <param name="obj">Any object</param>
|
||||
/// <param name="type">Numric type</param>
|
||||
/// <returns>Numeric value or null if the object is not a numeric value.</returns>
|
||||
public static object CastToNumericType(this Type type, object obj)
|
||||
{
|
||||
var doubleValue = CastToDouble(obj);
|
||||
if (double.IsNaN(doubleValue))
|
||||
return null;
|
||||
|
||||
if (obj is decimal && type == typeof(decimal))
|
||||
return obj; // do not convert into double
|
||||
|
||||
object result = null;
|
||||
if (type == typeof(sbyte))
|
||||
result = (sbyte)doubleValue;
|
||||
if (type == typeof(byte))
|
||||
result = (byte)doubleValue;
|
||||
if (type == typeof(short))
|
||||
result = (short)doubleValue;
|
||||
if (type == typeof(ushort))
|
||||
result = (ushort)doubleValue;
|
||||
if (type == typeof(int))
|
||||
result = (int)doubleValue;
|
||||
if (type == typeof(uint))
|
||||
result = (uint)doubleValue;
|
||||
if (type == typeof(long))
|
||||
result = (long)doubleValue;
|
||||
if (type == typeof(ulong))
|
||||
result = (ulong)doubleValue;
|
||||
if (type == typeof(float))
|
||||
result = (float)doubleValue;
|
||||
if (type == typeof(double))
|
||||
result = doubleValue;
|
||||
if (type == typeof(decimal))
|
||||
result = (decimal)doubleValue;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cast boxed numeric value to double
|
||||
/// </summary>
|
||||
/// <param name="obj">boxed numeric value</param>
|
||||
/// <returns>Numeric value in double. Double.Nan if obj is not a numeric value.</returns>
|
||||
public static double CastToDouble(object obj)
|
||||
{
|
||||
var result = double.NaN;
|
||||
var type = obj != null ? obj.GetType() : null;
|
||||
if (type == typeof(sbyte))
|
||||
result = (double)(sbyte)obj;
|
||||
if (type == typeof(byte))
|
||||
result = (double)(byte)obj;
|
||||
if (type == typeof(short))
|
||||
result = (double)(short)obj;
|
||||
if (type == typeof(ushort))
|
||||
result = (double)(ushort)obj;
|
||||
if (type == typeof(int))
|
||||
result = (double)(int)obj;
|
||||
if (type == typeof(uint))
|
||||
result = (double)(uint)obj;
|
||||
if (type == typeof(long))
|
||||
result = (double)(long)obj;
|
||||
if (type == typeof(ulong))
|
||||
result = (double)(ulong)obj;
|
||||
if (type == typeof(float))
|
||||
result = (double)(float)obj;
|
||||
if (type == typeof(double))
|
||||
result = (double)obj;
|
||||
if (type == typeof(decimal))
|
||||
result = (double)(decimal)obj;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -84,8 +84,72 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Scanner.cs" />
|
||||
<Compile Include="SemanticErrorException.cs" />
|
||||
<Compile Include="Serialization\AnchorNotFoundException.cs" />
|
||||
<Compile Include="Serialization\ArrayDescriptor.cs" />
|
||||
<Compile Include="Serialization\CollectionDescriptor.cs" />
|
||||
<Compile Include="Serialization\DefaultDescriptorFactory.cs" />
|
||||
<Compile Include="Serialization\DictionaryDescriptor.cs" />
|
||||
<Compile Include="Serialization\DocumentLoadingState.cs" />
|
||||
<Compile Include="Serialization\DuplicateAnchorException.cs" />
|
||||
<Compile Include="Serialization\EmitterState.cs" />
|
||||
<Compile Include="Serialization\FieldDescriptor.cs" />
|
||||
<Compile Include="Serialization\IAttributeRegistry.cs" />
|
||||
<Compile Include="Serialization\IMemberDescriptor.cs" />
|
||||
<Compile Include="Serialization\ITypeDescriptor.cs" />
|
||||
<Compile Include="Serialization\ITypeDescriptorFactory.cs" />
|
||||
<Compile Include="Serialization\IYamlVisitor.cs" />
|
||||
<Compile Include="Serialization\MemberDescriptorBase.cs" />
|
||||
<Compile Include="Serialization\ObjectDescriptor.cs" />
|
||||
<Compile Include="Serialization\Processors\AnchorProcessor.cs" />
|
||||
<Compile Include="Serialization\ChainedEventEmitter.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Serialization\Processors\ChainedProcessor.cs" />
|
||||
<Compile Include="Serialization\EventInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Serialization\IdentityEqualityComparer.cs" />
|
||||
<Compile Include="Serialization\IEventEmitter.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Serialization\IYamlProcessor.cs" />
|
||||
<Compile Include="Serialization\IYamlSerializableFactory.cs" />
|
||||
<Compile Include="Serialization\JsonEventEmitter.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Serialization\Processors\DictionaryProcessor.cs" />
|
||||
<Compile Include="Serialization\Processors\ObjectProcessor.cs" />
|
||||
<Compile Include="Serialization\PropertyDescriptor.cs" />
|
||||
<Compile Include="Serialization\SerializerContext.cs" />
|
||||
<Compile Include="Serialization\DefaultAttributeRegistry.cs" />
|
||||
<Compile Include="Serialization\TagRegistry.cs" />
|
||||
<Compile Include="Serialization\TypeAssigningEventEmitter.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Serialization\WriterEventEmitter.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Serialization\YamlAliasNode.cs" />
|
||||
<Compile Include="Serialization\YamlDocument.cs" />
|
||||
<Compile Include="Serialization\YamlFormatter.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Serialization\YamlIgnoreAttribute.cs" />
|
||||
<Compile Include="Serialization\YamlMappingNode.cs" />
|
||||
<Compile Include="Serialization\YamlMemberAttribute.cs" />
|
||||
<Compile Include="Serialization\YamlNode.cs" />
|
||||
<Compile Include="Serialization\YamlNodeIdentityEqualityComparer.cs" />
|
||||
<Compile Include="Serialization\YamlScalarNode.cs" />
|
||||
<Compile Include="Serialization\YamlSequenceNode.cs" />
|
||||
<Compile Include="Serialization\YamlSerializableMethod.cs" />
|
||||
<Compile Include="Serialization\YamlSerializer.cs" />
|
||||
<Compile Include="Serialization\YamlSerializerSettings.cs" />
|
||||
<Compile Include="Serialization\YamlStream.cs" />
|
||||
<Compile Include="Serialization\YamlTagAttribute.cs" />
|
||||
<Compile Include="Serialization\YamlVisitor.cs" />
|
||||
<Compile Include="SimpleKey.cs" />
|
||||
<Compile Include="SortedDictionary.cs" />
|
||||
<Compile Include="StringExtensions.cs" />
|
||||
<Compile Include="StringLookAheadBuffer.cs" />
|
||||
<Compile Include="SyntaxErrorException.cs" />
|
||||
<Compile Include="TagDirectiveCollection.cs" />
|
||||
|
@ -112,6 +176,7 @@
|
|||
<Compile Include="Tokens\Token.cs" />
|
||||
<Compile Include="Tokens\Value.cs" />
|
||||
<Compile Include="Tokens\VersionDirective.cs" />
|
||||
<Compile Include="TypeExtensions.cs" />
|
||||
<Compile Include="Version.cs" />
|
||||
<Compile Include="YamlException.cs" />
|
||||
</ItemGroup>
|
||||
|
|
Загрузка…
Ссылка в новой задаче