Skip to content

Commit 3febc70

Browse files
committed
updated serialization overrides to no longer depend on connectionsettings
1 parent c086546 commit 3febc70

File tree

8 files changed

+133
-137
lines changed

8 files changed

+133
-137
lines changed

src/Elasticsearch.Net/Configuration/ConnectionConfiguration.cs

Lines changed: 69 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using System.ComponentModel;
44

55
namespace Elasticsearch.Net
6-
{
6+
{
77
/// <summary>
88
/// ConnectionConfiguration allows you to control how ElasticsearchClient behaves and where/how it connects
99
/// to elasticsearch
@@ -12,40 +12,40 @@ public class ConnectionConfiguration : ConnectionConfiguration<ConnectionConfigu
1212
{
1313
public static TimeSpan DefaultTimeout = TimeSpan.FromMinutes(1);
1414
public static TimeSpan DefaultPingTimeout = TimeSpan.FromSeconds(2);
15-
public static TimeSpan DefaultPingTimeoutOnSSL = TimeSpan.FromSeconds(5);
16-
15+
public static TimeSpan DefaultPingTimeoutOnSSL = TimeSpan.FromSeconds(5);
16+
1717
/// <summary>
1818
/// ConnectionConfiguration allows you to control how ElasticsearchClient behaves and where/how it connects
1919
/// to elasticsearch
2020
/// </summary>
2121
/// <param name="uri">The root of the elasticsearch node we want to connect to. Defaults to http://localhost:9200</param>
2222
public ConnectionConfiguration(Uri uri = null)
23-
: this(new SingleNodeConnectionPool(uri ?? new Uri("http://localhost:9200")))
24-
{ }
25-
23+
: this(new SingleNodeConnectionPool(uri ?? new Uri("http://localhost:9200")))
24+
{ }
25+
2626
/// <summary>
2727
/// ConnectionConfiguration allows you to control how ElasticsearchClient behaves and where/how it connects
2828
/// to elasticsearch
2929
/// </summary>
3030
/// <param name="connectionPool">A connection pool implementation that'll tell the client what nodes are available</param>
31-
public ConnectionConfiguration(IConnectionPool connectionPool)
32-
// ReSharper disable once IntroduceOptionalParameters.Global
33-
: this(connectionPool, null, null)
31+
public ConnectionConfiguration(IConnectionPool connectionPool)
32+
// ReSharper disable once IntroduceOptionalParameters.Global
33+
: this(connectionPool, null, null)
3434
{ }
3535

36-
public ConnectionConfiguration(IConnectionPool connectionPool, IConnection connection)
37-
// ReSharper disable once IntroduceOptionalParameters.Global
38-
: this(connectionPool, connection, null)
36+
public ConnectionConfiguration(IConnectionPool connectionPool, IConnection connection)
37+
// ReSharper disable once IntroduceOptionalParameters.Global
38+
: this(connectionPool, connection, null)
3939
{ }
4040

41-
public ConnectionConfiguration(IConnectionPool connectionPool, IElasticsearchSerializer serializer)
42-
: this(connectionPool, null, serializer)
43-
{ }
44-
45-
// ReSharper disable once MemberCanBePrivate.Global
46-
// eventhough we use don't use this we very much would like to expose this constructor
47-
public ConnectionConfiguration(IConnectionPool connectionPool, IConnection connection, IElasticsearchSerializer serializer)
48-
: base(connectionPool, connection, serializer)
41+
public ConnectionConfiguration(IConnectionPool connectionPool, Func<ConnectionConfiguration, IElasticsearchSerializer> serializerFactory)
42+
: this(connectionPool, null, serializerFactory)
43+
{ }
44+
45+
// ReSharper disable once MemberCanBePrivate.Global
46+
// eventhough we use don't use this we very much would like to expose this constructor
47+
public ConnectionConfiguration(IConnectionPool connectionPool, IConnection connection, Func<ConnectionConfiguration, IElasticsearchSerializer> serializerFactory)
48+
: base(connectionPool, connection, serializerFactory)
4949
{ }
5050
}
5151

@@ -130,24 +130,26 @@ private static void DefaultApiCallHandler(IApiCallDetails status) { }
130130
BasicAuthenticationCredentials _basicAuthCredentials;
131131
BasicAuthenticationCredentials IConnectionConfigurationValues.BasicAuthenticationCredentials => _basicAuthCredentials;
132132

133-
private readonly IElasticsearchSerializer _serializer;
133+
protected IElasticsearchSerializer _serializer;
134134
IElasticsearchSerializer IConnectionConfigurationValues.Serializer => _serializer;
135135

136136
private readonly IConnectionPool _connectionPool;
137+
private readonly Func<T, IElasticsearchSerializer> _serializerFactory;
137138
IConnectionPool IConnectionConfigurationValues.ConnectionPool => _connectionPool;
138139

139140
private readonly IConnection _connection;
140141
IConnection IConnectionConfigurationValues.Connection => _connection;
141142

142143
[System.Diagnostics.CodeAnalysis.SuppressMessage(
143-
"Potential Code Quality Issues", "RECS0021:Warns about calls to virtual member functions occuring in the constructor",
144+
"Potential Code Quality Issues", "RECS0021:Warns about calls to virtual member functions occuring in the constructor",
144145
Justification = "We want the virtual method to run on most derived")]
145-
protected ConnectionConfiguration(IConnectionPool connectionPool, IConnection connection, IElasticsearchSerializer serializer)
146+
protected ConnectionConfiguration(IConnectionPool connectionPool, IConnection connection, Func<T, IElasticsearchSerializer> serializerFactory)
146147
{
147148
this._connectionPool = connectionPool;
148-
this._connection = connection ?? new HttpConnection();
149-
// ReSharper disable once VirtualMemberCallInContructor
150-
this._serializer = serializer ?? this.DefaultSerializer();
149+
this._connection = connection ?? new HttpConnection();
150+
this._serializerFactory = serializerFactory ?? (c=>this.DefaultSerializer((T)this));
151+
// ReSharper disable once VirtualMemberCallInContructor
152+
this._serializer = this._serializerFactory((T)this);
151153

152154
this._requestTimeout = ConnectionConfiguration.DefaultTimeout;
153155
this._sniffOnConnectionFault = true;
@@ -157,100 +159,100 @@ protected ConnectionConfiguration(IConnectionPool connectionPool, IConnection co
157159

158160
T Assign(Action<ConnectionConfiguration<T>> assigner) => Fluent.Assign((T)this, assigner);
159161

160-
protected virtual IElasticsearchSerializer DefaultSerializer() => new ElasticsearchDefaultSerializer();
162+
protected virtual IElasticsearchSerializer DefaultSerializer(T settings) => new ElasticsearchDefaultSerializer();
161163

162164
public T EnableTcpKeepAlive(TimeSpan keepAliveTime, TimeSpan keepAliveInterval) =>
163165
Assign(a => { this._keepAliveTime = keepAliveTime; this._keepAliveInterval = keepAliveInterval; });
164166

165-
public T MaximumRetries(int maxRetries) => Assign(a => a._maxRetries = maxRetries);
166-
167+
public T MaximumRetries(int maxRetries) => Assign(a => a._maxRetries = maxRetries);
168+
167169
/// <summary>
168170
/// On connection pools that support reseeding setting this to true (default) will resniff the cluster when a call fails
169171
/// </summary>
170-
public T SniffOnConnectionFault(bool sniffsOnConnectionFault = true) => Assign(a => a._sniffOnConnectionFault = sniffsOnConnectionFault);
171-
172+
public T SniffOnConnectionFault(bool sniffsOnConnectionFault = true) => Assign(a => a._sniffOnConnectionFault = sniffsOnConnectionFault);
173+
172174
/// <summary>
173175
/// Enables sniffing on first usage of a connection pool if that pool supports reseeding, defaults to true
174176
/// </summary>
175-
public T SniffOnStartup(bool sniffsOnStartup = true) => Assign(a => a._sniffOnStartup = sniffsOnStartup);
176-
177+
public T SniffOnStartup(bool sniffsOnStartup = true) => Assign(a => a._sniffOnStartup = sniffsOnStartup);
178+
177179
/// <summary>
178180
/// Set the duration after which a cluster state is considered stale and a sniff should be performed again.
179181
/// An IConnectionPool has to signal it supports reseeding otherwise sniffing will never happen.
180182
/// Defaults to 1 hour.
181183
/// Set to null to disable completely. Sniffing will only ever happen on ConnectionPools that return true for SupportsReseeding
182184
/// </summary>
183185
/// <param name="sniffLifeSpan">The duration a clusterstate is considered fresh, set to null to disable periodic sniffing</param>
184-
public T SniffLifeSpan(TimeSpan? sniffLifeSpan) => Assign(a => a._sniffLifeSpan = sniffLifeSpan);
185-
186+
public T SniffLifeSpan(TimeSpan? sniffLifeSpan) => Assign(a => a._sniffLifeSpan = sniffLifeSpan);
187+
186188
/// <summary>
187189
/// Enable gzip compressed requests and responses, do note that you need to configure elasticsearch to set this
188190
/// <para>http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-http.html"</para>
189191
/// </summary>
190192
public T EnableHttpCompression(bool enabled = true) => Assign(a => a._enableHttpCompression = enabled);
191193

192-
public T DisableAutomaticProxyDetection(bool disable = true) => Assign(a => a._disableAutomaticProxyDetection = disable);
193-
194+
public T DisableAutomaticProxyDetection(bool disable = true) => Assign(a => a._disableAutomaticProxyDetection = disable);
195+
194196
/// <summary>
195197
/// Instead of following a c/go like error checking on response.IsValid always throw an exception
196198
/// on the client when a call resulted in an exception on either the client or the Elasticsearch server.
197199
/// <para>Reasons for such exceptions could be search parser errors, index missing exceptions, etc...</para>
198200
/// </summary>
199-
public T ThrowExceptions(bool alwaysThrow = true) => Assign(a => a._throwExceptions = alwaysThrow);
200-
201+
public T ThrowExceptions(bool alwaysThrow = true) => Assign(a => a._throwExceptions = alwaysThrow);
202+
201203
/// <summary>
202204
/// When a node is used for the very first time or when it's used for the first time after it has been marked dead
203205
/// a ping with a very low timeout is send to the node to make sure that when it's still dead it reports it as fast as possible.
204206
/// You can disable these pings globally here if you rather have it fail on the possible slower original request
205207
/// </summary>
206-
public T DisablePing(bool disable = true) => Assign(a => a._disablePings = disable);
207-
208+
public T DisablePing(bool disable = true) => Assign(a => a._disablePings = disable);
209+
208210
/// <summary>
209211
/// This NameValueCollection will be appended to every url NEST calls, great if you need to pass i.e an API key.
210212
/// </summary>
211-
public T GlobalQueryStringParameters(NameValueCollection queryStringParameters) => Assign(a => a._queryString.Add(queryStringParameters));
212-
213+
public T GlobalQueryStringParameters(NameValueCollection queryStringParameters) => Assign(a => a._queryString.Add(queryStringParameters));
214+
213215
/// <summary>
214216
/// a NameValueCollection that will be send as headers for each request
215217
/// </summary>
216-
public T GlobalHeaders(NameValueCollection headers) => Assign(a => a._headers.Add(headers));
217-
218+
public T GlobalHeaders(NameValueCollection headers) => Assign(a => a._headers.Add(headers));
219+
218220
/// <summary>
219221
/// Sets the default timeout in milliseconds for each request to Elasticsearch.
220222
/// NOTE: You can set this to a high value here, and specify the timeout on Elasticsearch's side.
221223
/// </summary>
222224
/// <param name="timeout">time out in milliseconds</param>
223-
public T RequestTimeout(TimeSpan timeout) => Assign(a => a._requestTimeout = timeout);
224-
225+
public T RequestTimeout(TimeSpan timeout) => Assign(a => a._requestTimeout = timeout);
226+
225227
/// <summary>
226228
/// Sets the default ping timeout in milliseconds for ping requests, which are used
227229
/// to determine whether a node is alive. Pings should fail as fast as possible.
228230
/// </summary>
229231
/// <param name="timeout">The ping timeout in milliseconds defaults to 1000, or 2000 is using SSL.</param>
230-
public T PingTimeout(TimeSpan timeout) => Assign(a => a._pingTimeout = timeout);
231-
232+
public T PingTimeout(TimeSpan timeout) => Assign(a => a._pingTimeout = timeout);
233+
232234
/// <summary>
233235
/// Sets the default dead timeout factor when a node has been marked dead.
234236
/// </summary>
235237
/// <remarks>Some connection pools may use a flat timeout whilst others take this factor and increase it exponentially</remarks>
236238
/// <param name="timeout"></param>
237-
public T DeadTimeout(TimeSpan timeout) => Assign(a => a._deadTimeout = timeout);
238-
239+
public T DeadTimeout(TimeSpan timeout) => Assign(a => a._deadTimeout = timeout);
240+
239241
/// <summary>
240242
/// Sets the maximum time a node can be marked dead.
241243
/// Different implementations of IConnectionPool may choose a different default.
242244
/// </summary>
243245
/// <param name="timeout">The timeout in milliseconds</param>
244-
public T MaxDeadTimeout(TimeSpan timeout) => Assign(a => a._maxDeadTimeout = timeout);
245-
246+
public T MaxDeadTimeout(TimeSpan timeout) => Assign(a => a._maxDeadTimeout = timeout);
247+
246248
/// <summary>
247249
/// Limits the total runtime including retries separately from <see cref="RequestTimeout"/>
248250
/// <pre>
249251
/// When not specified defaults to <see cref="RequestTimeout"/> which itself defaults to 60seconds
250252
/// </pre>
251253
/// </summary>
252-
public T MaxRetryTimeout(TimeSpan maxRetryTimeout) => Assign(a => a._maxRetryTimeout = maxRetryTimeout);
253-
254+
public T MaxRetryTimeout(TimeSpan maxRetryTimeout) => Assign(a => a._maxRetryTimeout = maxRetryTimeout);
255+
254256
/// <summary>
255257
/// If your connection has to go through proxy use this method to specify the proxy url
256258
/// </summary>
@@ -261,33 +263,33 @@ public T Proxy(Uri proxyAdress, string username, string password)
261263
this._proxyUsername = username;
262264
this._proxyPassword = password;
263265
return (T)this;
264-
}
265-
266+
}
267+
266268
/// <summary>
267269
/// Forces all requests to have ?pretty=true, causing elasticsearch to return formatted json.
268270
/// Also forces the client to send out formatted json. Defaults to false
269271
/// </summary>
270-
public T PrettyJson(bool b = true) => Assign(a =>
272+
public T PrettyJson(bool b = true) => Assign(a =>
271273
{
272274
this._prettyJson = b;
273275
if (!b && this._queryString["pretty"] != null) this._queryString.Remove("pretty");
274276
else if (b && this._queryString["pretty"] == null)
275-
this.GlobalQueryStringParameters(new NameValueCollection { { "pretty", b.ToString().ToLowerInvariant() } });
276-
});
277-
277+
this.GlobalQueryStringParameters(new NameValueCollection { { "pretty", b.ToString().ToLowerInvariant() } });
278+
});
279+
278280
/// <summary>
279281
/// Make sure the reponse bytes are always available on the ElasticsearchResponse object
280282
/// <para>Note: that depending on the registered serializer this may cause the respond to be read in memory first</para>
281283
/// </summary>
282-
public T DisableDirectStreaming(bool b = true) => Assign(a => a._disableDirectStreaming = b);
283-
284+
public T DisableDirectStreaming(bool b = true) => Assign(a => a._disableDirectStreaming = b);
285+
284286
/// <summary>
285287
/// Global callback for every response that NEST receives, useful for custom logging.
286288
/// Calling this multiple times will register multiple listeners
287289
/// </summary>
288290
public T ConnectionStatusHandler(Action<IApiCallDetails> handler) =>
289-
Assign(a => a._apiCallHandler += handler ?? DefaultApiCallHandler);
290-
291+
Assign(a => a._apiCallHandler += handler ?? DefaultApiCallHandler);
292+
291293
/// <summary>
292294
/// Basic access authentication credentials to specify with all requests.
293295
/// </summary>
@@ -299,8 +301,8 @@ public T BasicAuthentication(string userName, string password)
299301
Password = password
300302
};
301303
return (T)this;
302-
}
303-
304+
}
305+
304306
/// <summary>
305307
/// Allows for requests to be pipelined. http://en.wikipedia.org/wiki/HTTP_pipelining
306308
/// <para>Note: HTTP pipelining must also be enabled in Elasticsearch for this to work properly.</para>

src/Nest/CommonAbstractions/ConnectionSettings/ConnectionSettings.cs

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ public ConnectionSettings(IConnectionPool connectionPool)
2424
public ConnectionSettings(IConnectionPool connectionPool, IConnection connection)
2525
: this(connectionPool, connection, null) { }
2626

27-
public ConnectionSettings(IConnectionPool connectionPool, IElasticsearchSerializer serializer)
28-
: this(connectionPool, null, serializer) { }
27+
public ConnectionSettings(IConnectionPool connectionPool, Func<ConnectionSettings, IElasticsearchSerializer> serializerFactory)
28+
: this(connectionPool, null, serializerFactory) { }
2929

30-
public ConnectionSettings(IConnectionPool connectionPool, IConnection connection, IElasticsearchSerializer serializer)
31-
: base(connectionPool, connection, serializer) { }
30+
public ConnectionSettings(IConnectionPool connectionPool, IConnection connection, Func<ConnectionSettings, IElasticsearchSerializer> serializerFactory)
31+
: base(connectionPool, connection, serializerFactory) { }
3232
}
3333

3434
/// <summary>
@@ -57,37 +57,28 @@ public abstract class ConnectionSettings<TConnectionSettings> : ConnectionConfig
5757
private Func<string, string> _defaultFieldNameInferrer;
5858
Func<string, string> IConnectionSettingsValues.DefaultFieldNameInferrer => _defaultFieldNameInferrer;
5959

60-
//Serializer settings
61-
private Action<JsonSerializerSettings> _modifyJsonSerializerSettings;
62-
Action<JsonSerializerSettings> IConnectionSettingsValues.ModifyJsonSerializerSettings => _modifyJsonSerializerSettings;
63-
64-
private ReadOnlyCollection<Func<Type, JsonConverter>> _contractConverters;
65-
ReadOnlyCollection<Func<Type, JsonConverter>> IConnectionSettingsValues.ContractConverters => _contractConverters;
66-
6760
private readonly FluentDictionary<Type, string> _idProperties = new FluentDictionary<Type, string>();
6861
FluentDictionary<Type, string> IConnectionSettingsValues.IdProperties => _idProperties;
6962

7063
private readonly FluentDictionary<MemberInfo, IPropertyMapping> _propertyMappings = new FluentDictionary<MemberInfo, IPropertyMapping>();
7164
FluentDictionary<MemberInfo, IPropertyMapping> IConnectionSettingsValues.PropertyMappings => _propertyMappings;
7265

73-
protected ConnectionSettings(IConnectionPool connectionPool, IConnection connection, IElasticsearchSerializer serializer)
74-
: base(connectionPool, connection, serializer)
66+
protected ConnectionSettings(IConnectionPool connectionPool, IConnection connection, Func<TConnectionSettings, IElasticsearchSerializer> serializerFactory)
67+
: base(connectionPool, connection, serializerFactory)
7568
{
7669
this._defaultTypeNameInferrer = (t => t.Name.ToLowerInvariant());
7770
this._defaultFieldNameInferrer = (p => p.ToCamelCase());
7871
this._defaultIndices = new FluentDictionary<Type, string>();
7972
this._defaultTypeNames = new FluentDictionary<Type, string>();
8073

81-
this._modifyJsonSerializerSettings = j => { };
82-
this._contractConverters = Enumerable.Empty<Func<Type, JsonConverter>>().ToList().AsReadOnly();
8374
this._inferrer = new ElasticInferrer(this);
8475
}
8576

8677
/// <summary>
8778
/// The default serializer for requests and responses
8879
/// </summary>
8980
/// <returns></returns>
90-
protected override IElasticsearchSerializer DefaultSerializer() => new JsonNetSerializer(this);
81+
protected override IElasticsearchSerializer DefaultSerializer(TConnectionSettings settings) => new JsonNetSerializer(settings);
9182

9283
/// <summary>
9384
/// This calls SetDefaultTypenameInferrer with an implementation that will pluralize type names. This used to be the default prior to Nest 0.90
@@ -98,26 +89,6 @@ public TConnectionSettings PluralizeTypeNames()
9889
return (TConnectionSettings)this;
9990
}
10091

101-
/// <summary>
102-
/// Allows you to update internal the json.net serializer settings to your liking
103-
/// </summary>
104-
public TConnectionSettings JsonSerializerSettingsModifier(Action<JsonSerializerSettings> modifier)
105-
{
106-
if (modifier == null)
107-
return (TConnectionSettings)this;
108-
this._modifyJsonSerializerSettings = modifier;
109-
return (TConnectionSettings)this;
110-
111-
}
112-
/// <summary>
113-
/// Add a custom JsonConverter to the build in json serialization by passing in a predicate for a type.
114-
/// </summary>
115-
public TConnectionSettings AddContractJsonConverters(params Func<Type, JsonConverter>[] contractSelectors)
116-
{
117-
this._contractConverters = contractSelectors.ToList().AsReadOnly();
118-
return (TConnectionSettings)this;
119-
}
120-
12192
/// <summary>
12293
/// The default index to use when no index is specified.
12394
/// </summary>

src/Nest/CommonAbstractions/ConnectionSettings/IConnectionSettingsValues.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,5 @@ public interface IConnectionSettingsValues : IConnectionConfigurationValues
1616
string DefaultIndex { get; }
1717
Func<string, string> DefaultFieldNameInferrer { get; }
1818
Func<Type, string> DefaultTypeNameInferrer { get; }
19-
Action<JsonSerializerSettings> ModifyJsonSerializerSettings { get; }
20-
ReadOnlyCollection<Func<Type, JsonConverter>> ContractConverters { get; }
2119
}
2220
}

src/Nest/CommonAbstractions/Extensions/TypeExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ internal static class TypeExtensions
2323

2424
//this contract is only used to resolve properties in class WE OWN.
2525
//these are not subject to change depending on what the user passes as connectionsettings
26-
private static ElasticContractResolver _jsonContract = new ElasticContractResolver(new ConnectionSettings());
26+
private static ElasticContractResolver _jsonContract = new ElasticContractResolver(new ConnectionSettings(), null);
2727

2828
public delegate T ObjectActivator<out T>(params object[] args);
2929

0 commit comments

Comments
 (0)