зеркало из https://github.com/stride3d/SharpYaml.git
Start to rewrite serialization (WIP)
This commit is contained in:
Родитель
8bee539624
Коммит
df7c220db8
|
@ -66,7 +66,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
||||||
<Project>{BF32DE1B-6276-4341-B212-F8862ADBBA7A}</Project>
|
<Project>{BF32DE1B-6276-4341-B212-F8862ADBBA7A}</Project>
|
||||||
<Name>YamlDotNet.Core</Name>
|
<Name>YamlDotNet</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -78,7 +78,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
||||||
<Project>{BF32DE1B-6276-4341-B212-F8862ADBBA7A}</Project>
|
<Project>{BF32DE1B-6276-4341-B212-F8862ADBBA7A}</Project>
|
||||||
<Name>YamlDotNet.Core</Name>
|
<Name>YamlDotNet</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
||||||
<Project>{21CA0077-E15C-446D-9C43-F6D3F9D09687}</Project>
|
<Project>{21CA0077-E15C-446D-9C43-F6D3F9D09687}</Project>
|
||||||
|
|
|
@ -61,9 +61,9 @@
|
||||||
<Project>{6a8dcaf7-6c13-4ada-aed9-7aba88fe7717}</Project>
|
<Project>{6a8dcaf7-6c13-4ada-aed9-7aba88fe7717}</Project>
|
||||||
<Name>YamlDotNet.Converters</Name>
|
<Name>YamlDotNet.Converters</Name>
|
||||||
</ProjectReference>
|
</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>
|
<Project>{16d8043d-c3db-4868-bff3-b2ebdf537aaa}</Project>
|
||||||
<Name>YamlDotNet.Core.Test</Name>
|
<Name>YamlDotNet.Test</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
||||||
<Project>{21ca0077-e15c-446d-9c43-f6d3f9d09687}</Project>
|
<Project>{21ca0077-e15c-446d-9c43-f6d3f9d09687}</Project>
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="FakeItEasy">
|
<Reference Include="FakeItEasy">
|
||||||
<HintPath>..\packages\FakeItEasy.1.13.1\lib\net40\FakeItEasy.dll</HintPath>
|
<HintPath>..\packages\FakeItEasy.1.13.1\lib\net40\FakeItEasy.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="FluentAssertions">
|
<Reference Include="FluentAssertions">
|
||||||
|
@ -100,11 +100,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
||||||
<Project>{bf32de1b-6276-4341-b212-f8862adbba7a}</Project>
|
<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>
|
|
||||||
<Name>YamlDotNet.Serialzation</Name>
|
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
@ -65,13 +65,13 @@
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<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>
|
<Project>{16d8043d-c3db-4868-bff3-b2ebdf537aaa}</Project>
|
||||||
<Name>YamlDotNet.Core.Test</Name>
|
<Name>YamlDotNet.Test</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
||||||
<Project>{bf32de1b-6276-4341-b212-f8862adbba7a}</Project>
|
<Project>{bf32de1b-6276-4341-b212-f8862adbba7a}</Project>
|
||||||
<Name>YamlDotNet.Core</Name>
|
<Name>YamlDotNet</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
||||||
<Project>{21ca0077-e15c-446d-9c43-f6d3f9d09687}</Project>
|
<Project>{21ca0077-e15c-446d-9c43-f6d3f9d09687}</Project>
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj">
|
||||||
<Project>{BF32DE1B-6276-4341-B212-F8862ADBBA7A}</Project>
|
<Project>{BF32DE1B-6276-4341-B212-F8862ADBBA7A}</Project>
|
||||||
<Name>YamlDotNet.Core</Name>
|
<Name>YamlDotNet</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
<ProjectReference Include="..\YamlDotNet.RepresentationModel\YamlDotNet.Serialzation.csproj">
|
||||||
<Project>{21CA0077-E15C-446D-9C43-F6D3F9D09687}</Project>
|
<Project>{21CA0077-E15C-446D-9C43-F6D3F9D09687}</Project>
|
||||||
|
|
|
@ -34,14 +34,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{8DC198
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.Converters.Test", "YamlDotNet.Converters.Test\YamlDotNet.Converters.Test.csproj", "{F0EAB124-9790-41C7-AE0F-F050CA0141D3}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.Converters.Test", "YamlDotNet.Converters.Test\YamlDotNet.Converters.Test.csproj", "{F0EAB124-9790-41C7-AE0F-F050CA0141D3}"
|
||||||
EndProject
|
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
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.RepresentationModel.Test", "YamlDotNet.RepresentationModel.Test\YamlDotNet.RepresentationModel.Test.csproj", "{FF969DAA-C025-4636-89B2-46F16821FA02}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.RepresentationModel.Test", "YamlDotNet.RepresentationModel.Test\YamlDotNet.RepresentationModel.Test.csproj", "{FF969DAA-C025-4636-89B2-46F16821FA02}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.Dynamic", "YamlDotNet.Dynamic\YamlDotNet.Dynamic.csproj", "{57B52D79-04A0-4091-8EE2-B419C009C2A6}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.Dynamic", "YamlDotNet.Dynamic\YamlDotNet.Dynamic.csproj", "{57B52D79-04A0-4091-8EE2-B419C009C2A6}"
|
||||||
EndProject
|
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}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YamlDotNet.Dynamic.UnitTests", "YamlDotNet.Dynamic.UnitTests\YamlDotNet.Dynamic.UnitTests.csproj", "{6E3BEF5A-2DBA-4941-972D-BD6AF27B4A71}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
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.ActiveCfg = Debug|Any CPU
|
||||||
{16D8043D-C3DB-4868-BFF3-B2EBDF537AAA}.Debug|Any CPU.Build.0 = 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.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}.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.ActiveCfg = Release|Any CPU
|
||||||
{16D8043D-C3DB-4868-BFF3-B2EBDF537AAA}.Release|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{57B52D79-04A0-4091-8EE2-B419C009C2A6}.Release|Mixed Platforms.Build.0 = 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
|
{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.ActiveCfg = Debug|Any CPU
|
||||||
{6E3BEF5A-2DBA-4941-972D-BD6AF27B4A71}.Debug|Any CPU.Build.0 = 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
|
{6E3BEF5A-2DBA-4941-972D-BD6AF27B4A71}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
|
|
@ -20,15 +20,12 @@
|
||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using YamlDotNet;
|
|
||||||
|
|
||||||
namespace YamlDotNet.Serialization
|
namespace YamlDotNet.Serialization
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The exception that is thrown when an alias references an anchor that does not exist.
|
/// The exception that is thrown when an alias references an anchor that does not exist.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
|
||||||
public class AnchorNotFoundException : YamlException
|
public class AnchorNotFoundException : YamlException
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <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.
|
// SOFTWARE.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.Serialization;
|
|
||||||
using YamlDotNet;
|
|
||||||
|
|
||||||
namespace YamlDotNet.Serialization
|
namespace YamlDotNet.Serialization
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The exception that is thrown when a duplicate anchor is detected.
|
/// The exception that is thrown when a duplicate anchor is detected.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
|
||||||
public class DuplicateAnchorException : YamlException
|
public class DuplicateAnchorException : YamlException
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using YamlDotNet;
|
|
||||||
using YamlDotNet.Events;
|
using YamlDotNet.Events;
|
||||||
|
|
||||||
namespace YamlDotNet.Serialization
|
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
|
namespace YamlDotNet.Serialization
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface used to write YAML events.
|
||||||
|
/// </summary>
|
||||||
public interface IEventEmitter
|
public interface IEventEmitter
|
||||||
{
|
{
|
||||||
void Emit(AliasEventInfo eventInfo);
|
void Emit(AliasEventInfo eventInfo);
|
||||||
|
|
||||||
void Emit(ScalarEventInfo eventInfo);
|
void Emit(ScalarEventInfo eventInfo);
|
||||||
|
|
||||||
void Emit(MappingStartEventInfo eventInfo);
|
void Emit(MappingStartEventInfo eventInfo);
|
||||||
|
|
||||||
void Emit(MappingEndEventInfo eventInfo);
|
void Emit(MappingEndEventInfo eventInfo);
|
||||||
|
|
||||||
void Emit(SequenceStartEventInfo eventInfo);
|
void Emit(SequenceStartEventInfo eventInfo);
|
||||||
|
|
||||||
void Emit(SequenceEndEventInfo 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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace YamlDotNet.Serialization
|
namespace YamlDotNet.Serialization
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides access to the properties of a type.
|
/// Provides access members of a type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITypeDescriptor
|
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
|
/// <summary>
|
||||||
{
|
/// Gets the member count.
|
||||||
string Name { get; }
|
/// </summary>
|
||||||
PropertyInfo Property { get; }
|
/// <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.
|
// SOFTWARE.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using YamlDotNet;
|
|
||||||
|
|
||||||
namespace YamlDotNet.Serialization
|
namespace YamlDotNet.Serialization
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows an object to customize how it is serialized and deserialized.
|
/// Allows an object to customize how it is serialized and deserialized.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IYamlSerializable
|
public interface IYamlProcessor
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads this object's state from a YAML parser.
|
/// Reads this object's state from a YAML parser.
|
||||||
/// </summary>
|
/// </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>
|
/// <summary>
|
||||||
/// Writes this object's state to a YAML emitter.
|
/// Writes this object's state to a YAML emitter.
|
||||||
/// </summary>
|
/// </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
|
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; }
|
/// <summary>
|
||||||
public string Name { get; private set; }
|
/// 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
|
public sealed class WriterEventEmitter : IEventEmitter
|
||||||
{
|
{
|
||||||
private readonly IEmitter emitter;
|
private readonly IEmitter emitter;
|
||||||
|
private readonly SerializerContext context;
|
||||||
|
|
||||||
public WriterEventEmitter(IEmitter emitter)
|
public WriterEventEmitter(IEmitter emitter, SerializerContext context)
|
||||||
{
|
{
|
||||||
this.emitter = emitter;
|
this.emitter = emitter;
|
||||||
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IEventEmitter.Emit(AliasEventInfo eventInfo)
|
void IEventEmitter.Emit(AliasEventInfo eventInfo)
|
||||||
|
@ -19,12 +21,12 @@ namespace YamlDotNet.Serialization
|
||||||
|
|
||||||
void IEventEmitter.Emit(ScalarEventInfo eventInfo)
|
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)
|
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)
|
void IEventEmitter.Emit(MappingEndEventInfo eventInfo)
|
||||||
|
@ -34,7 +36,7 @@ namespace YamlDotNet.Serialization
|
||||||
|
|
||||||
void IEventEmitter.Emit(SequenceStartEventInfo eventInfo)
|
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)
|
void IEventEmitter.Emit(SequenceEndEventInfo eventInfo)
|
||||||
|
|
|
@ -2,12 +2,12 @@ using System;
|
||||||
|
|
||||||
namespace YamlDotNet.Serialization
|
namespace YamlDotNet.Serialization
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Instructs the YamlSerializer not to serialize the public field or public read/write property value.
|
/// Instructs the YamlSerializer not to serialize the public field or public read/write property value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
|
||||||
public sealed class YamlIgnoreAttribute : Attribute
|
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="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Scanner.cs" />
|
<Compile Include="Scanner.cs" />
|
||||||
<Compile Include="SemanticErrorException.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="SimpleKey.cs" />
|
||||||
<Compile Include="SortedDictionary.cs" />
|
<Compile Include="SortedDictionary.cs" />
|
||||||
|
<Compile Include="StringExtensions.cs" />
|
||||||
<Compile Include="StringLookAheadBuffer.cs" />
|
<Compile Include="StringLookAheadBuffer.cs" />
|
||||||
<Compile Include="SyntaxErrorException.cs" />
|
<Compile Include="SyntaxErrorException.cs" />
|
||||||
<Compile Include="TagDirectiveCollection.cs" />
|
<Compile Include="TagDirectiveCollection.cs" />
|
||||||
|
@ -112,6 +176,7 @@
|
||||||
<Compile Include="Tokens\Token.cs" />
|
<Compile Include="Tokens\Token.cs" />
|
||||||
<Compile Include="Tokens\Value.cs" />
|
<Compile Include="Tokens\Value.cs" />
|
||||||
<Compile Include="Tokens\VersionDirective.cs" />
|
<Compile Include="Tokens\VersionDirective.cs" />
|
||||||
|
<Compile Include="TypeExtensions.cs" />
|
||||||
<Compile Include="Version.cs" />
|
<Compile Include="Version.cs" />
|
||||||
<Compile Include="YamlException.cs" />
|
<Compile Include="YamlException.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче