Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions src/Nest/CommonAbstractions/Extensions/TypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ internal static class TypeExtensions
private static readonly MethodInfo GetActivatorMethodInfo =
typeof(TypeExtensions).GetMethod(nameof(GetActivator), BindingFlags.Static | BindingFlags.NonPublic);

private static readonly ConcurrentDictionary<Type, Func<object>> CachedDefaultValues =
new ConcurrentDictionary<Type, Func<object>>();

private static readonly ConcurrentDictionary<string, ObjectActivator<object>> CachedActivators =
new ConcurrentDictionary<string, ObjectActivator<object>>();

Expand All @@ -29,17 +32,14 @@ internal static class TypeExtensions

private delegate T ObjectActivator<out T>(params object[] args);

internal static object CreateGenericInstance(this Type t, Type closeOver, params object[] args)
{
return t.CreateGenericInstance(new[] {closeOver}, args);
}
internal static object CreateGenericInstance(this Type t, Type closeOver, params object[] args) =>
t.CreateGenericInstance(new[] {closeOver}, args);

internal static object CreateGenericInstance(this Type t, Type[] closeOver, params object[] args)
{
var argKey = closeOver.Aggregate(new StringBuilder(), (sb, gt) => sb.Append("--" + gt.FullName), sb => sb.ToString());
var key = t.FullName + argKey;
Type closedType;
if (!CachedGenericClosedTypes.TryGetValue(key, out closedType))
if (!CachedGenericClosedTypes.TryGetValue(key, out var closedType))
{
closedType = t.MakeGenericType(closeOver);
CachedGenericClosedTypes.TryAdd(key, closedType);
Expand Down Expand Up @@ -71,6 +71,15 @@ internal static object CreateInstance(this Type t, params object[] args)
return activator(args);
}

internal static object DefaultValue(this Type type) =>
type.IsValueType()
? CachedDefaultValues.GetOrAdd(type, t =>
Expression.Lambda<Func<object>>(
Expression.Convert(Expression.Default(type), typeof(object))
).Compile()
).Invoke()
: null;

//do not remove this is referenced through GetActivatorMethod
private static ObjectActivator<T> GetActivator<T>(ConstructorInfo ctor)
{
Expand All @@ -88,11 +97,8 @@ private static ObjectActivator<T> GetActivator<T>(ConstructorInfo ctor)
{
var index = Expression.Constant(i);
var paramType = paramsInfo[i].ParameterType;

var paramAccessorExp = Expression.ArrayIndex(param, index);

var paramCastExp = Expression.Convert(paramAccessorExp, paramType);

argsExp[i] = paramCastExp;
}

Expand Down Expand Up @@ -125,8 +131,7 @@ internal static IList<JsonProperty> GetCachedObjectProperties(this Type t,

internal static IList<PropertyInfo> AllPropertiesCached(this Type t)
{
IList<PropertyInfo> propertyInfos;
if (CachedTypePropertyInfos.TryGetValue(t, out propertyInfos))
if (CachedTypePropertyInfos.TryGetValue(t, out var propertyInfos))
return propertyInfos;
propertyInfos = t.AllPropertiesNotCached().ToList();
CachedTypePropertyInfos.TryAdd(t, propertyInfos);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq.Expressions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -14,6 +16,10 @@ namespace Nest
internal class InternalSerializer : IElasticsearchSerializer
{
private static readonly Encoding ExpectedEncoding = new UTF8Encoding(false);

//we still support net45 so Task.Completed is not available
private static readonly Task CompletedTask = Task.FromResult(false);

private readonly JsonSerializer _indentedSerializer;
internal JsonSerializer Serializer { get; }

Expand Down Expand Up @@ -66,8 +72,7 @@ public virtual void Serialize<T>(T data, Stream writableStream, SerializationFor
}
}

//we still support net45 so Task.Completed is not available
private static readonly Task CompletedTask = Task.FromResult(false);

public Task SerializeAsync<T>(T data, Stream stream, SerializationFormatting formatting = SerializationFormatting.Indented,
CancellationToken cancellationToken = default(CancellationToken))
{
Expand All @@ -77,13 +82,11 @@ public Task SerializeAsync<T>(T data, Stream stream, SerializationFormatting for
return CompletedTask;
}

public object Default(Type type) => type.IsValueType() ? type.CreateInstance() : null;

public virtual T Deserialize<T>(Stream stream) => (T) this.Deserialize(typeof(T), stream);
public T Deserialize<T>(Stream stream) => (T) this.Deserialize(typeof(T), stream);

public virtual object Deserialize(Type type, Stream stream)
public object Deserialize(Type type, Stream stream)
{
if (stream == null) return Default(type);
if (stream == null) return type.DefaultValue();
using (var streamReader = new StreamReader(stream))
using (var jsonTextReader = new JsonTextReader(streamReader))
{
Expand All @@ -92,8 +95,9 @@ public virtual object Deserialize(Type type, Stream stream)
}
}

public virtual async Task<T> DeserializeAsync<T>(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
public async Task<T> DeserializeAsync<T>(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{
if (stream == null) return default(T);
using (var streamReader = new StreamReader(stream))
using (var jsonTextReader = new JsonTextReader(streamReader))
{
Expand All @@ -108,18 +112,26 @@ public virtual object Deserialize(Type type, Stream stream)
}
catch
{
return await Task.FromResult(default(T)).ConfigureAwait(false);
return default(T);
}
}
}

public virtual async Task<object> DeserializeAsync(Type type, Stream stream, CancellationToken cancellationToken = default(CancellationToken))
public async Task<object> DeserializeAsync(Type type, Stream stream, CancellationToken cancellationToken = default(CancellationToken))
{
if (stream == null) return type.DefaultValue();
using (var streamReader = new StreamReader(stream))
using (var jsonTextReader = new JsonTextReader(streamReader))
{
var token = await JToken.LoadAsync(jsonTextReader, cancellationToken).ConfigureAwait(false);
return token.ToObject(type, this.Serializer);
try
{
var token = await JToken.LoadAsync(jsonTextReader, cancellationToken).ConfigureAwait(false);
return token.ToObject(type, this.Serializer);
}
catch
{
return type.DefaultValue();
}
}
}

Expand Down