Skip to content

Instantly share code, notes, and snippets.

@mysticatea
Created March 13, 2013 09:45
Show Gist options
  • Save mysticatea/5150623 to your computer and use it in GitHub Desktop.
Save mysticatea/5150623 to your computer and use it in GitHub Desktop.
The implement of IDataContractSurrogate for Immutable Collections.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
namespace Mysticatea.Util
{
/// <summary>
/// <see cref="N:System.Collections.Immutable"/>にあるクラスのインスタンスを Data Contracts にて永続化するための<see cref="IDataContractSurrogate"/>実装です。
/// </summary>
/// <remarks>
/// <see cref="N:System.Collections.Immutable"/>のコレクションたちは、Data Contracts を利用して書き込むための要件を満たしています。<br/>
/// しかし、読み込むための要件を満たしていません。<br/>
/// そこで、読み込むときだけ<see cref="List{T}"/>または<see cref="Dictionary{TKey,TValue}"/>として読み込み、後に<see cref="N:System.Collections.Immutable"/>のコレクションに変換します。
/// </remarks>
public class ImmutableCollectionsSurrogate : IDataContractSurrogate
{
/// <summary>
/// <see cref="ImmutableCollectionsSurrogate"/>の唯一のインスタンスを取得します。
/// </summary>
public static ImmutableCollectionsSurrogate Instance
{
get { return instance; }
}
#region IDataContractSurrogate メンバー
/// <inheritdoc/>
public Type GetDataContractType(Type type)
{
var typeName = type.Name;
if (ListPattern.IsMatch(typeName))
{
var gas = type.GetGenericArguments();
return Type.GetType("System.Collections.Generic.List`1[[" + gas[0].AssemblyQualifiedName + "]]");
}
if (DictPattern.IsMatch(typeName))
{
var gas = type.GetGenericArguments();
return Type.GetType("System.Collections.Generic.Dictionary`2[[" + gas[0].AssemblyQualifiedName + "],[" + gas[1].AssemblyQualifiedName + "]]");
}
return type;
}
/// <inheritdoc/>
public object GetDeserializedObject(object obj, Type targetType)
{
switch (targetType.Name)
{
case "ImmutableDictionary`2":
return ImmutableDictionary.ToImmutableDictionary((dynamic) obj);
case "ImmutableHashSet`1":
return ImmutableHashSet.ToImmutableHashSet((dynamic) obj);
case "ImmutableList`1":
return ImmutableList.ToImmutableList((dynamic) obj);
case "ImmutableQueue`1":
return ImmutableQueue.Create((dynamic) obj);
case "ImmutableSortedDictionary`2":
return ImmutableSortedDictionary.ToImmutableSortedDictionary((dynamic) obj);
case "ImmutableSortedSet`1":
return ImmutableSortedSet.ToImmutableSortedSet((dynamic) obj);
case "ImmutableStack`1":
return ImmutableStack.Create((dynamic) obj);
}
return obj;
}
#region 未使用
object IDataContractSurrogate.GetObjectToSerialize(object obj, Type targetType)
{
return obj;
}
Type IDataContractSurrogate.GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
return null;
}
System.CodeDom.CodeTypeDeclaration IDataContractSurrogate.ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{
return typeDeclaration;
}
object IDataContractSurrogate.GetCustomDataToExport(Type clrType, Type dataContractType)
{
return null;
}
object IDataContractSurrogate.GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
return null;
}
void IDataContractSurrogate.GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection<Type> customDataTypes)
{
// do nothing.
}
#endregion
#endregion
#region 非公開メンバー
private static readonly ImmutableCollectionsSurrogate instance = new ImmutableCollectionsSurrogate();
private ImmutableCollectionsSurrogate() { }
private readonly Regex ListPattern = new Regex("Immutable(?:List|(?:Hash|Sorted)Set|Queue|Stack)`1");
private readonly Regex DictPattern = new Regex("Immutable(?:Sorted)?Dictionary`2");
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment