Skip to content

Commit d9b879b

Browse files
committed
Another attempt to fix #2182 #2183
Taking another approach then #2189. Here we yield responsibility of creating a new client to ISerializerFactory. The overloads taking a Func factory are now obsolete and others taking ISerializerFactory are added
1 parent b2ad5dd commit d9b879b

18 files changed

+468
-61
lines changed

src/Elasticsearch.Net/Configuration/ConnectionConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ protected ConnectionConfiguration(IConnectionPool connectionPool, IConnection co
160160
{
161161
this._connectionPool = connectionPool;
162162
this._connection = connection ?? new HttpConnection();
163-
this._serializerFactory = serializerFactory ?? (c=>this.DefaultSerializer((T)this));
163+
this._serializerFactory = serializerFactory ?? (c => this.DefaultSerializer((T)this));
164164
// ReSharper disable once VirtualMemberCallInContructor
165165
this._serializer = _serializerFactory((T)this);
166166

src/Elasticsearch.Net/Serialization/IElasticsearchSerializer.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ public static byte[] SerializeToBytes(this IElasticsearchSerializer serializer,
2626
return ms.ToArray();
2727
}
2828
}
29-
public static string SerializeToString(this IElasticsearchSerializer serializer, object data, SerializationFormatting formatting = SerializationFormatting.Indented) =>
29+
public static string SerializeToString(this IElasticsearchSerializer serializer, object data, SerializationFormatting formatting = SerializationFormatting.Indented) =>
3030
serializer.SerializeToBytes(data, formatting).Utf8String();
3131
}
32-
33-
}
32+
}

src/Nest/CommonAbstractions/ConnectionSettings/ConnectionSettingsBase.cs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,21 @@ public ConnectionSettings(Uri uri = null)
1919
: this(new SingleNodeConnectionPool(uri ?? new Uri("http://localhost:9200"))) { }
2020

2121
public ConnectionSettings(IConnectionPool connectionPool)
22-
: this(connectionPool, null, null) { }
22+
: this(connectionPool, null, new SerializerFactory()) { }
2323

2424
public ConnectionSettings(IConnectionPool connectionPool, IConnection connection)
25-
: this(connectionPool, connection, null) { }
25+
: this(connectionPool, connection, new SerializerFactory()) { }
2626

2727
public ConnectionSettings(IConnectionPool connectionPool, Func<ConnectionSettings, IElasticsearchSerializer> serializerFactory)
2828
: this(connectionPool, null, serializerFactory) { }
2929

30+
public ConnectionSettings(IConnectionPool connectionPool, IConnection connection, ISerializerFactory serializerFactory)
31+
: base(connectionPool, connection, serializerFactory, s => serializerFactory.Create(s)) { }
32+
33+
[Obsolete("Please use the constructor taking ISerializerFactory instead of a Func")]
3034
public ConnectionSettings(IConnectionPool connectionPool, IConnection connection, Func<ConnectionSettings, IElasticsearchSerializer> serializerFactory)
31-
: base(connectionPool, connection, serializerFactory) { }
35+
: base(connectionPool, connection, null, s => serializerFactory(s)) { }
36+
3237
}
3338

3439
/// <summary>
@@ -37,7 +42,7 @@ public ConnectionSettings(IConnectionPool connectionPool, IConnection connection
3742
[Browsable(false)]
3843
[EditorBrowsable(EditorBrowsableState.Never)]
3944
public abstract class ConnectionSettingsBase<TConnectionSettings> : ConnectionConfiguration<TConnectionSettings>, IConnectionSettingsValues
40-
where TConnectionSettings : ConnectionSettingsBase<TConnectionSettings>
45+
where TConnectionSettings : ConnectionSettingsBase<TConnectionSettings>, IConnectionSettingsValues
4146
{
4247
private string _defaultIndex;
4348
string IConnectionSettingsValues.DefaultIndex => this._defaultIndex;
@@ -63,17 +68,36 @@ public abstract class ConnectionSettingsBase<TConnectionSettings> : ConnectionCo
6368
private readonly FluentDictionary<MemberInfo, IPropertyMapping> _propertyMappings = new FluentDictionary<MemberInfo, IPropertyMapping>();
6469
FluentDictionary<MemberInfo, IPropertyMapping> IConnectionSettingsValues.PropertyMappings => _propertyMappings;
6570

66-
protected ConnectionSettingsBase(IConnectionPool connectionPool, IConnection connection, Func<TConnectionSettings, IElasticsearchSerializer> serializerFactory)
67-
: base(connectionPool, connection, serializerFactory)
71+
private readonly ISerializerFactory _serializerFactory;
72+
ISerializerFactory IConnectionSettingsValues.SerializerFactory { get; }
73+
74+
protected ConnectionSettingsBase(
75+
IConnectionPool connectionPool,
76+
IConnection connection,
77+
ISerializerFactory serializerFactory,
78+
Func<TConnectionSettings, IElasticsearchSerializer> serializerFactoryFunc
79+
)
80+
: base(connectionPool, connection, serializerFactoryFunc)
6881
{
6982
this._defaultTypeNameInferrer = (t => t.Name.ToLowerInvariant());
7083
this._defaultFieldNameInferrer = (p => p.ToCamelCase());
7184
this._defaultIndices = new FluentDictionary<Type, string>();
7285
this._defaultTypeNames = new FluentDictionary<Type, string>();
86+
this._serializerFactory = serializerFactory ?? new SerializerFactory();
7387

7488
this._inferrer = new Inferrer(this);
7589
}
7690

91+
protected ConnectionSettingsBase(
92+
IConnectionPool connectionPool,
93+
IConnection connection,
94+
Func<TConnectionSettings, IElasticsearchSerializer> serializerFactoryFunc
95+
)
96+
: this(connectionPool, connection, null, serializerFactoryFunc) { }
97+
98+
IElasticsearchSerializer IConnectionSettingsValues.CreateStatefulSerializer(JsonConverter converter) =>
99+
this._serializerFactory.CreateStateful(this, converter);
100+
77101
/// <summary>
78102
/// The default serializer for requests and responses
79103
/// </summary>
@@ -92,7 +116,7 @@ public TConnectionSettings PluralizeTypeNames()
92116
/// <summary>
93117
/// The default index to use when no index is specified.
94118
/// </summary>
95-
/// <param name="defaultIndex">When null/empty/not set might throw
119+
/// <param name="defaultIndex">When null/empty/not set might throw
96120
/// <see cref="NullReferenceException"/> later on when not specifying index explicitly while indexing.
97121
/// </param>
98122
public TConnectionSettings DefaultIndex(string defaultIndex)
@@ -177,10 +201,10 @@ public TConnectionSettings MapPropertiesFor<TDocument>(Action<PropertyMappingDes
177201
var mapper = new PropertyMappingDescriptor<TDocument>();
178202
propertiesSelector(mapper);
179203
ApplyPropertyMappings(mapper.Mappings);
180-
return (TConnectionSettings) this;
204+
return (TConnectionSettings)this;
181205
}
182206

183-
private void ApplyPropertyMappings<TDocument>(IList<IClrTypePropertyMapping<TDocument>> mappings)
207+
private void ApplyPropertyMappings<TDocument>(IList<IClrTypePropertyMapping<TDocument>> mappings)
184208
where TDocument : class
185209
{
186210
foreach (var mapping in mappings)
@@ -198,7 +222,7 @@ private void ApplyPropertyMappings<TDocument>(IList<IClrTypePropertyMapping<TDoc
198222
{
199223
var newName = mapping.NewName;
200224
var mappedAs = _propertyMappings[memberInfo].Name;
201-
var typeName = typeof (TDocument).Name;
225+
var typeName = typeof(TDocument).Name;
202226
if (mappedAs.IsNullOrEmpty() && newName.IsNullOrEmpty())
203227
throw new ArgumentException("Property mapping '{0}' on type is already ignored"
204228
.F(e, newName, mappedAs, typeName));
@@ -228,12 +252,12 @@ public TConnectionSettings InferMappingFor<TDocument>(Func<ClrTypeMappingDescrip
228252
if (inferMapping.IdProperty != null)
229253
#pragma warning disable CS0618 // Type or member is obsolete but will be private in the future OK to call here
230254
this.MapIdPropertyFor<TDocument>(inferMapping.IdProperty);
231-
#pragma warning restore CS0618
255+
#pragma warning restore CS0618
232256

233257
if (inferMapping.Properties != null)
234258
this.ApplyPropertyMappings<TDocument>(inferMapping.Properties);
235-
236-
return (TConnectionSettings) this;
259+
260+
return (TConnectionSettings)this;
237261
}
238262

239263
}

src/Nest/CommonAbstractions/ConnectionSettings/IConnectionSettingsValues.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,9 @@ public interface IConnectionSettingsValues : IConnectionConfigurationValues
1616
string DefaultIndex { get; }
1717
Func<string, string> DefaultFieldNameInferrer { get; }
1818
Func<Type, string> DefaultTypeNameInferrer { get; }
19+
20+
ISerializerFactory SerializerFactory { get; }
21+
22+
IElasticsearchSerializer CreateStatefulSerializer(JsonConverter converter);
1923
}
20-
}
24+
}

src/Nest/CommonAbstractions/SerializationBehavior/JsonNetSerializer.cs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,41 +15,64 @@ public class JsonNetSerializer : IElasticsearchSerializer
1515
{
1616
private static readonly Encoding ExpectedEncoding = new UTF8Encoding(false);
1717

18+
1819
protected IConnectionSettingsValues Settings { get; }
1920
protected ElasticContractResolver ContractResolver { get; }
2021

2122
//todo this internal smells
2223
internal JsonSerializer Serializer => _defaultSerializer;
2324

24-
private readonly Dictionary<SerializationFormatting, JsonSerializer> _defaultSerializers;
25-
private readonly JsonSerializer _defaultSerializer;
25+
private Dictionary<SerializationFormatting, JsonSerializer> _defaultSerializers;
26+
private JsonSerializer _defaultSerializer;
2627

28+
[Obsolete("Use the connection settings constructor that takes an ISerializerFactory")]
2729
protected virtual void ModifyJsonSerializerSettings(JsonSerializerSettings settings) { }
30+
2831
protected virtual IList<Func<Type, JsonConverter>> ContractConverters => null;
2932

3033
public JsonNetSerializer(IConnectionSettingsValues settings) : this(settings, null) { }
3134

3235
/// <summary>
33-
/// this constructor is only here for stateful (de)serialization
36+
/// this constructor is only here for stateful (de)serialization
3437
/// </summary>
35-
internal JsonNetSerializer(IConnectionSettingsValues settings, JsonConverter stateFullConverter)
38+
protected internal JsonNetSerializer(
39+
IConnectionSettingsValues settings,
40+
JsonConverter stateFullConverter
41+
)
3642
{
3743
this.Settings = settings;
44+
3845
var piggyBackState = stateFullConverter == null ? null : new JsonConverterPiggyBackState { ActualJsonConverter = stateFullConverter };
3946
// ReSharper disable once VirtualMemberCallInContructor
4047
this.ContractResolver = new ElasticContractResolver(this.Settings, this.ContractConverters) { PiggyBackState = piggyBackState };
4148

4249
this._defaultSerializer = JsonSerializer.Create(this.CreateSettings(SerializationFormatting.None));
43-
//this._defaultSerializer.Formatting = Formatting.None;
4450
var indentedSerializer = JsonSerializer.Create(this.CreateSettings(SerializationFormatting.Indented));
45-
//indentedSerializer.Formatting = Formatting.Indented;
4651
this._defaultSerializers = new Dictionary<SerializationFormatting, JsonSerializer>
4752
{
4853
{ SerializationFormatting.None, this._defaultSerializer },
4954
{ SerializationFormatting.Indented, indentedSerializer }
5055
};
5156
}
5257

58+
protected void CreateCustomJsonSerializers(Action<JsonSerializerSettings, IConnectionSettingsValues> s)
59+
{
60+
var collapsed = this.CreateSettings(SerializationFormatting.None);
61+
var indented = this.CreateSettings(SerializationFormatting.Indented);
62+
s(collapsed, this.Settings);
63+
s(indented, this.Settings);
64+
65+
this._defaultSerializer = JsonSerializer.Create(collapsed);
66+
var indentedSerializer = JsonSerializer.Create(indented);
67+
this._defaultSerializers = new Dictionary<SerializationFormatting, JsonSerializer>
68+
{
69+
{ SerializationFormatting.None, this._defaultSerializer },
70+
{ SerializationFormatting.Indented, indentedSerializer }
71+
};
72+
73+
}
74+
75+
5376
public virtual void Serialize(object data, Stream writableStream, SerializationFormatting formatting = SerializationFormatting.Indented)
5477
{
5578
var serializer = _defaultSerializers[formatting];
@@ -117,4 +140,4 @@ private JsonSerializerSettings CreateSettings(SerializationFormatting formatting
117140
return settings;
118141
}
119142
}
120-
}
143+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using Elasticsearch.Net;
7+
using Newtonsoft.Json;
8+
9+
namespace Nest
10+
{
11+
public interface ISerializerFactory
12+
{
13+
IElasticsearchSerializer Create(IConnectionSettingsValues settings);
14+
15+
IElasticsearchSerializer CreateStateful(IConnectionSettingsValues settings, JsonConverter converter);
16+
}
17+
18+
public class SerializerFactory : ISerializerFactory
19+
{
20+
private Func<IConnectionSettingsValues, IElasticsearchSerializer> _serializerFactoryFunc;
21+
22+
public SerializerFactory()
23+
{
24+
25+
}
26+
public SerializerFactory(Func<IConnectionSettingsValues , IElasticsearchSerializer> serializerFactoryFunc)
27+
{
28+
this._serializerFactoryFunc = serializerFactoryFunc;
29+
}
30+
31+
public IElasticsearchSerializer Create(IConnectionSettingsValues settings)
32+
{
33+
return this._serializerFactoryFunc?.Invoke(settings) ?? new JsonNetSerializer(settings);
34+
}
35+
36+
public IElasticsearchSerializer CreateStateful(IConnectionSettingsValues settings, JsonConverter converter)
37+
{
38+
return new JsonNetSerializer(settings, converter);
39+
}
40+
}
41+
}

src/Nest/Document/Multiple/MultiGet/ElasticClient-MultiGet.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
namespace Nest
88
{
99
using MultiGetConverter = Func<IApiCallDetails, Stream, MultiGetResponse>;
10-
10+
1111
public partial interface IElasticClient
1212
{
1313
/// <summary>
14-
/// Multi GET API allows to get multiple documents based on an index, type (optional) and id (and possibly routing).
15-
/// The response includes a docs array with all the fetched documents, each element similar in structure to a document
14+
/// Multi GET API allows to get multiple documents based on an index, type (optional) and id (and possibly routing).
15+
/// The response includes a docs array with all the fetched documents, each element similar in structure to a document
1616
/// provided by the get API.
1717
/// <para> </para>http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-multi-get.html
1818
/// </summary>
@@ -36,7 +36,7 @@ public IMultiGetResponse MultiGet(Func<MultiGetDescriptor, IMultiGetRequest> sel
3636
this.MultiGet(selector.InvokeOrDefault(new MultiGetDescriptor()));
3737

3838
/// <inheritdoc/>
39-
public IMultiGetResponse MultiGet(IMultiGetRequest request) =>
39+
public IMultiGetResponse MultiGet(IMultiGetRequest request) =>
4040
this.Dispatcher.Dispatch<IMultiGetRequest, MultiGetRequestParameters, MultiGetResponse>(
4141
request,
4242
new MultiGetConverter((r, s) => this.DeserializeMultiGetResponse(r, s, CreateCovariantMultiGetConverter(request))),
@@ -48,16 +48,16 @@ public Task<IMultiGetResponse> MultiGetAsync(Func<MultiGetDescriptor, IMultiGetR
4848
this.MultiGetAsync(selector.InvokeOrDefault(new MultiGetDescriptor()));
4949

5050
/// <inheritdoc/>
51-
public Task<IMultiGetResponse> MultiGetAsync(IMultiGetRequest request) =>
51+
public Task<IMultiGetResponse> MultiGetAsync(IMultiGetRequest request) =>
5252
this.Dispatcher.DispatchAsync<IMultiGetRequest, MultiGetRequestParameters, MultiGetResponse, IMultiGetResponse>(
5353
request,
5454
new MultiGetConverter((r, s) => this.DeserializeMultiGetResponse(r, s, CreateCovariantMultiGetConverter(request))),
5555
this.LowLevelDispatch.MgetDispatchAsync<MultiGetResponse>
5656
);
57-
private MultiGetResponse DeserializeMultiGetResponse(IApiCallDetails response, Stream stream, JsonConverter converter)=>
58-
new JsonNetSerializer(this.ConnectionSettings, converter).Deserialize<MultiGetResponse>(stream);
57+
private MultiGetResponse DeserializeMultiGetResponse(IApiCallDetails response, Stream stream, JsonConverter converter) =>
58+
this.ConnectionSettings.CreateStatefulSerializer(converter).Deserialize<MultiGetResponse>(stream);
5959

6060
private JsonConverter CreateCovariantMultiGetConverter(IMultiGetRequest descriptor) => new MultiGetHitJsonConverter(descriptor);
6161

6262
}
63-
}
63+
}

src/Nest/Nest.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@
456456
<Compile Include="CommonAbstractions\SerializationBehavior\GenericJsonConverters\VerbatimDictionaryKeysConverter.cs" />
457457
<Compile Include="CommonAbstractions\SerializationBehavior\JsonNetSerializer.cs" />
458458
<Compile Include="CommonAbstractions\SerializationBehavior\JsonReaderExtensions.cs" />
459+
<Compile Include="CommonAbstractions\SerializationBehavior\SerializerFactory.cs" />
459460
<Compile Include="CommonAbstractions\SerializationBehavior\StatefulDeserialization\ConcreteTypeConverter.cs" />
460461
<Compile Include="CommonAbstractions\SerializationBehavior\StatefulDeserialization\JsonConverterPiggyBackState.cs" />
461462
<Compile Include="CommonAbstractions\Static\Static.cs" />

src/Nest/Search/MultiSearch/ElasticClient-MultiSearch.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public IMultiSearchResponse MultiSearch(IMultiSearchRequest request)
4141
(p, d) =>
4242
{
4343
var converter = CreateMultiSearchDeserializer(p);
44-
var serializer = new JsonNetSerializer(this.ConnectionSettings, converter);
44+
var serializer = this.ConnectionSettings.CreateStatefulSerializer(converter);
4545
var json = serializer.SerializeToBytes(p).Utf8String();
4646
var creator = new MultiSearchCreator((r, s) => serializer.Deserialize<MultiSearchResponse>(s));
4747
request.RequestParameters.DeserializationOverride(creator);
@@ -63,7 +63,7 @@ public Task<IMultiSearchResponse> MultiSearchAsync(IMultiSearchRequest request)
6363
(p, d) =>
6464
{
6565
var converter = CreateMultiSearchDeserializer(p);
66-
var serializer = new JsonNetSerializer(this.ConnectionSettings, converter);
66+
var serializer = this.ConnectionSettings.CreateStatefulSerializer(converter);
6767
var json = serializer.SerializeToBytes(p).Utf8String();
6868
var creator = new MultiSearchCreator((r, s) => serializer.Deserialize<MultiSearchResponse>(s));
6969
request.RequestParameters.DeserializationOverride(creator);
@@ -83,4 +83,4 @@ private JsonConverter CreateMultiSearchDeserializer(IMultiSearchRequest request)
8383
return new MultiSearchResponseJsonConverter(this.ConnectionSettings, request);
8484
}
8585
}
86-
}
86+
}

src/Nest/Search/MultiSearch/MultiSearchResponseJsonConverter.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,23 +54,23 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
5454
var descriptor = m.Descriptor.Value;
5555
var concreteTypeSelector = descriptor.TypeSelector;
5656
var baseType = m.Descriptor.Value.ClrType ?? typeof(object);
57-
57+
5858
var generic = MakeDelegateMethodInfo.MakeGenericMethod(baseType);
5959

6060
if (concreteTypeSelector != null)
6161
{
6262
var state = typeof(ConcreteTypeConverter<>).CreateGenericInstance(baseType, concreteTypeSelector) as JsonConverter;
6363
if (state != null)
6464
{
65-
var elasticSerializer = new JsonNetSerializer(this._settings, state);
65+
var elasticSerializer = this._settings.CreateStatefulSerializer(state);
6666

67-
generic.Invoke(null, new object[] { m, elasticSerializer.Serializer, response.Responses, this._settings });
67+
generic.Invoke(null, new object[] { m, elasticSerializer, response.Responses, this._settings });
6868
continue;
6969
}
7070
}
7171
generic.Invoke(null, new object[] { m, serializer, response.Responses, this._settings });
7272
}
73-
73+
7474
return response;
7575
}
7676

@@ -86,9 +86,9 @@ private class MultiHitTuple
8686
}
8787

8888
private static void CreateMultiHit<T>(
89-
MultiHitTuple tuple,
90-
JsonSerializer serializer,
91-
IDictionary<string, object> collection,
89+
MultiHitTuple tuple,
90+
JsonSerializer serializer,
91+
IDictionary<string, object> collection,
9292
IConnectionSettingsValues settings
9393
)
9494
where T : class

0 commit comments

Comments
 (0)