diff options
-rw-r--r-- | sandbox/Sandbox/Program.cs | 24 | ||||
-rw-r--r-- | src/MessagePack/Formatters/CollectionFormatter.cs | 218 | ||||
-rw-r--r-- | src/MessagePack/Formatters/IMessagePackFormatter.cs | 8 | ||||
-rw-r--r-- | src/MessagePack/Formatters/IgnoreFormatter.cs | 16 | ||||
-rw-r--r-- | src/MessagePack/Resolvers/CompositeResolver.cs | 51 | ||||
-rw-r--r-- | src/MessagePack/Resolvers/DynamicGenericResolver.cs | 21 | ||||
-rw-r--r-- | tests/MessagePack.Tests/MessagePack.Tests.csproj | 1 | ||||
-rw-r--r-- | tests/MessagePack.Tests/NonGenericCollectionTest.cs | 60 |
8 files changed, 390 insertions, 9 deletions
diff --git a/sandbox/Sandbox/Program.cs b/sandbox/Sandbox/Program.cs index 67862abe..5ffb46a3 100644 --- a/sandbox/Sandbox/Program.cs +++ b/sandbox/Sandbox/Program.cs @@ -16,6 +16,7 @@ using Newtonsoft.Json; using System.Text; using System.IO.Compression; using System.Collections.Concurrent; +using System.Reflection; namespace Sandbox { @@ -280,21 +281,32 @@ namespace Sandbox public IEntity Entity { get; } } + public class Dummy___ + { + public MethodBase MyProperty { get; set; } + } class Program { static void Main(string[] args) { + try + { + throw new InvalidOperationException("foo bar"); + } + catch (Exception ex) + { + // var ex = new Dummy___(); - var gb = 1024 * 1024 * 1024; - byte[] bytes = null; - MessagePackBinary.EnsureCapacity(ref bytes, 0, gb); - MessagePackBinary.EnsureCapacity(ref bytes, gb, 1); - - MessagePackBinary.EnsureCapacity(ref bytes, 0x7FFFFFC7, 1); + MessagePack.Resolvers.CompositeResolver.RegisterAndSetAsDefault( + new[] { new IgnoreFormatter<MethodBase>() }, + new[] { ContractlessStandardResolver.Instance }); + var bin = MessagePack.MessagePackSerializer.Serialize(ex); + Console.WriteLine(MessagePack.MessagePackSerializer.ToJson(bin)); + } } static void Benchmark<T>(T target) diff --git a/src/MessagePack/Formatters/CollectionFormatter.cs b/src/MessagePack/Formatters/CollectionFormatter.cs index f2dc69df..0dc6bd55 100644 --- a/src/MessagePack/Formatters/CollectionFormatter.cs +++ b/src/MessagePack/Formatters/CollectionFormatter.cs @@ -703,6 +703,224 @@ namespace MessagePack.Formatters } } + // NonGenerics + + public sealed class NonGenericListFormatter<T> : IMessagePackFormatter<T> + where T : class, IList, new() + { + public int Serialize(ref byte[] bytes, int offset, T value, IFormatterResolver formatterResolver) + { + if (value == null) + { + MessagePackBinary.WriteNil(ref bytes, offset); + return 1; + } + + var formatter = formatterResolver.GetFormatterWithVerify<object>(); + var startOffset = offset; + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Count); + foreach (var item in value) + { + offset += formatter.Serialize(ref bytes, offset, item, formatterResolver); + } + + return offset - startOffset; + } + + public T Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return default(T); + } + + var formatter = formatterResolver.GetFormatterWithVerify<object>(); + var startOffset = offset; + + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + var list = new T(); + for (int i = 0; i < count; i++) + { + list.Add(formatter.Deserialize(bytes, offset, formatterResolver, out readSize)); + offset += readSize; + } + + readSize = offset - startOffset; + return list; + } + } + + public sealed class NonGenericInterfaceListFormatter : IMessagePackFormatter<IList> + { + public static readonly IMessagePackFormatter<IList> Instance = new NonGenericInterfaceListFormatter(); + + NonGenericInterfaceListFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, IList value, IFormatterResolver formatterResolver) + { + if (value == null) + { + MessagePackBinary.WriteNil(ref bytes, offset); + return 1; + } + + var formatter = formatterResolver.GetFormatterWithVerify<object>(); + var startOffset = offset; + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Count); + foreach (var item in value) + { + offset += formatter.Serialize(ref bytes, offset, item, formatterResolver); + } + + return offset - startOffset; + } + + public IList Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return default(IList); + } + + var formatter = formatterResolver.GetFormatterWithVerify<object>(); + var startOffset = offset; + + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + var list = new object[count]; + for (int i = 0; i < count; i++) + { + list[i] = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + } + + readSize = offset - startOffset; + return list; + } + } + + public sealed class NonGenericDictionaryFormatter<T> : IMessagePackFormatter<T> + where T : class, IDictionary, new() + { + public int Serialize(ref byte[] bytes, int offset, T value, IFormatterResolver formatterResolver) + { + if (value == null) + { + MessagePackBinary.WriteNil(ref bytes, offset); + return 1; + } + + var formatter = formatterResolver.GetFormatterWithVerify<object>(); + var startOffset = offset; + + offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, value.Count); + foreach (DictionaryEntry item in value) + { + offset += formatter.Serialize(ref bytes, offset, item.Key, formatterResolver); + offset += formatter.Serialize(ref bytes, offset, item.Value, formatterResolver); + } + + return offset - startOffset; + } + + public T Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + + var formatter = formatterResolver.GetFormatterWithVerify<object>(); + var startOffset = offset; + + var count = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize); + offset += readSize; + + var dict = new T(); + for (int i = 0; i < count; i++) + { + var key = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var value = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + dict.Add(key, value); + } + + readSize = offset - startOffset; + return dict; + } + } + + public sealed class NonGenericInterfaceDictionaryFormatter : IMessagePackFormatter<IDictionary> + { + public static readonly IMessagePackFormatter<IDictionary> Instance = new NonGenericInterfaceDictionaryFormatter(); + + NonGenericInterfaceDictionaryFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, IDictionary value, IFormatterResolver formatterResolver) + { + if (value == null) + { + MessagePackBinary.WriteNil(ref bytes, offset); + return 1; + } + + var formatter = formatterResolver.GetFormatterWithVerify<object>(); + var startOffset = offset; + + offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, value.Count); + foreach (DictionaryEntry item in value) + { + offset += formatter.Serialize(ref bytes, offset, item.Key, formatterResolver); + offset += formatter.Serialize(ref bytes, offset, item.Value, formatterResolver); + } + + return offset - startOffset; + } + + public IDictionary Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + + var formatter = formatterResolver.GetFormatterWithVerify<object>(); + var startOffset = offset; + + var count = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize); + offset += readSize; + + var dict = new Dictionary<object, object>(count); + for (int i = 0; i < count; i++) + { + var key = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var value = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + dict.Add(key, value); + } + + readSize = offset - startOffset; + return dict; + } + } + #if NETSTANDARD1_4 public sealed class ObservableCollectionFormatter<T> : CollectionFormatterBase<T, ObservableCollection<T>> diff --git a/src/MessagePack/Formatters/IMessagePackFormatter.cs b/src/MessagePack/Formatters/IMessagePackFormatter.cs index 7015b21b..2ae40a15 100644 --- a/src/MessagePack/Formatters/IMessagePackFormatter.cs +++ b/src/MessagePack/Formatters/IMessagePackFormatter.cs @@ -1,7 +1,13 @@ namespace MessagePack.Formatters { - public interface IMessagePackFormatter<T> + // marker + public interface IMessagePackFormatter + { + + } + + public interface IMessagePackFormatter<T> : IMessagePackFormatter { int Serialize(ref byte[] bytes, int offset, T value, IFormatterResolver formatterResolver); T Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize); diff --git a/src/MessagePack/Formatters/IgnoreFormatter.cs b/src/MessagePack/Formatters/IgnoreFormatter.cs new file mode 100644 index 00000000..cbf38bac --- /dev/null +++ b/src/MessagePack/Formatters/IgnoreFormatter.cs @@ -0,0 +1,16 @@ +namespace MessagePack.Formatters +{ + public sealed class IgnoreFormatter<T> : IMessagePackFormatter<T> + { + public int Serialize(ref byte[] bytes, int offset, T value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + + public T Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + readSize = MessagePackBinary.ReadNextBlock(bytes, offset); + return default(T); + } + } +}
\ No newline at end of file diff --git a/src/MessagePack/Resolvers/CompositeResolver.cs b/src/MessagePack/Resolvers/CompositeResolver.cs index ea4b409e..beac4d22 100644 --- a/src/MessagePack/Resolvers/CompositeResolver.cs +++ b/src/MessagePack/Resolvers/CompositeResolver.cs @@ -1,7 +1,6 @@ using MessagePack.Formatters; using System; -using System.Collections.Generic; -using System.Text; +using System.Reflection; namespace MessagePack.Resolvers { @@ -10,6 +9,7 @@ namespace MessagePack.Resolvers public static readonly CompositeResolver Instance = new CompositeResolver(); static bool isFreezed = false; + static IMessagePackFormatter[] formatters = new IMessagePackFormatter[0]; static IFormatterResolver[] resolvers = new IFormatterResolver[0]; CompositeResolver() @@ -26,12 +26,46 @@ namespace MessagePack.Resolvers CompositeResolver.resolvers = resolvers; } + public static void Register(params IMessagePackFormatter[] formatters) + { + if (isFreezed) + { + throw new InvalidOperationException("Register must call on startup(before use GetFormatter<T>)."); + } + + CompositeResolver.formatters = formatters; + } + + public static void Register(IMessagePackFormatter[] formatters, IFormatterResolver[] resolvers) + { + if (isFreezed) + { + throw new InvalidOperationException("Register must call on startup(before use GetFormatter<T>)."); + } + + CompositeResolver.resolvers = resolvers; + CompositeResolver.formatters = formatters; + } + public static void RegisterAndSetAsDefault(params IFormatterResolver[] resolvers) { Register(resolvers); MessagePack.MessagePackSerializer.SetDefaultResolver(CompositeResolver.Instance); } + public static void RegisterAndSetAsDefault(params IMessagePackFormatter[] formatters) + { + Register(formatters); + MessagePack.MessagePackSerializer.SetDefaultResolver(CompositeResolver.Instance); + } + + public static void RegisterAndSetAsDefault(IMessagePackFormatter[] formatters, IFormatterResolver[] resolvers) + { + Register(formatters); + Register(resolvers); + MessagePack.MessagePackSerializer.SetDefaultResolver(CompositeResolver.Instance); + } + public IMessagePackFormatter<T> GetFormatter<T>() { return FormatterCache<T>.formatter; @@ -45,6 +79,19 @@ namespace MessagePack.Resolvers { isFreezed = true; + foreach (var item in formatters) + { + foreach (var implInterface in item.GetType().GetTypeInfo().ImplementedInterfaces) + { + var ti = implInterface.GetTypeInfo(); + if (ti.IsGenericType && ti.GenericTypeArguments[0] == typeof(T)) + { + formatter = (IMessagePackFormatter<T>)item; + return; + } + } + } + foreach (var item in resolvers) { var f = item.GetFormatter<T>(); diff --git a/src/MessagePack/Resolvers/DynamicGenericResolver.cs b/src/MessagePack/Resolvers/DynamicGenericResolver.cs index ef68368f..eb4f4fcb 100644 --- a/src/MessagePack/Resolvers/DynamicGenericResolver.cs +++ b/src/MessagePack/Resolvers/DynamicGenericResolver.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Reflection; using System.Collections.ObjectModel; +using System.Collections; #if NETSTANDARD1_4 using System.Threading.Tasks; @@ -268,6 +269,26 @@ namespace MessagePack.Internal } } } + else + { + // NonGeneric Collection + if (t == typeof(IList)) + { + return NonGenericInterfaceListFormatter.Instance; + } + else if (t == typeof(IDictionary)) + { + return NonGenericInterfaceDictionaryFormatter.Instance; + } + if (typeof(IList).GetTypeInfo().IsAssignableFrom(ti) && ti.DeclaredConstructors.Any(x => x.GetParameters().Length == 0)) + { + return Activator.CreateInstance(typeof(NonGenericListFormatter<>).MakeGenericType(t)); + } + else if (typeof(IDictionary).GetTypeInfo().IsAssignableFrom(ti) && ti.DeclaredConstructors.Any(x => x.GetParameters().Length == 0)) + { + return Activator.CreateInstance(typeof(NonGenericDictionaryFormatter<>).MakeGenericType(t)); + } + } return null; } diff --git a/tests/MessagePack.Tests/MessagePack.Tests.csproj b/tests/MessagePack.Tests/MessagePack.Tests.csproj index aabec998..5e934092 100644 --- a/tests/MessagePack.Tests/MessagePack.Tests.csproj +++ b/tests/MessagePack.Tests/MessagePack.Tests.csproj @@ -109,6 +109,7 @@ <Compile Include="CollectionTest.cs" /> <Compile Include="DataContractTest.cs" /> <Compile Include="DynamicObjectFallbackTest.cs" /> + <Compile Include="NonGenericCollectionTest.cs" /> <Compile Include="StreamStrictTest.cs" /> <Compile Include="ThreadsafeHashtableTest.cs" /> <Compile Include="TypelessContractlessStandardResolverTest.cs" /> diff --git a/tests/MessagePack.Tests/NonGenericCollectionTest.cs b/tests/MessagePack.Tests/NonGenericCollectionTest.cs new file mode 100644 index 00000000..857f9e1b --- /dev/null +++ b/tests/MessagePack.Tests/NonGenericCollectionTest.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace MessagePack.Tests +{ + public class NonGenericCollectionTest + { + [Fact] + public void List() + { + var xs = new System.Collections.ArrayList { 1, 100, "hoge", 999.888 }; + { + var bin = MessagePackSerializer.Serialize<IList>(xs); + var v = MessagePackSerializer.Deserialize<IList>(bin); + + ((byte)v[0]).Is((byte)1); + ((byte)v[1]).Is((byte)100); + ((string)v[2]).Is("hoge"); + ((double)v[3]).Is(999.888); + } + { + var bin = MessagePackSerializer.Serialize(xs); + var v = MessagePackSerializer.Deserialize<ArrayList>(bin); + + ((byte)v[0]).Is((byte)1); + ((byte)v[1]).Is((byte)100); + ((string)v[2]).Is("hoge"); + ((double)v[3]).Is(999.888); + } + } + + [Fact] + public void Dictionary() + { + { + var xs = new System.Collections.Hashtable { { "a", 1 }, { 100, "hoge" }, { "foo", 999.888 } }; + var bin = MessagePackSerializer.Serialize<IDictionary>(xs); + var v = MessagePackSerializer.Deserialize<IDictionary>(bin); + + v["a"].Is((object)(byte)1); + v[(byte)100].Is((object)(string)"hoge"); + v["foo"].Is((object)(double)999.888); + } + { + var xs = new System.Collections.Hashtable { { "a", 1 }, { 100, "hoge" }, { "foo", 999.888 } }; + var bin = MessagePackSerializer.Serialize<Hashtable>(xs); + var v = MessagePackSerializer.Deserialize<Hashtable>(bin); + + v["a"].Is((object)(byte)1); + v[(byte)100].Is((object)(string)"hoge"); + v["foo"].Is((object)(double)999.888); + } + } + } +} |