Skip to content

Commit 9ef244b

Browse files
committed
Serialization of some other types in Xtensive.Core
1 parent 9b0825f commit 9ef244b

File tree

2 files changed

+93
-67
lines changed

2 files changed

+93
-67
lines changed

Orm/Xtensive.Orm/Core/AssociateProvider.cs

Lines changed: 88 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2003-2010 Xtensive LLC.
1+
// Copyright (C) 2008-2021 Xtensive LLC.
22
// All rights reserved.
33
// For conditions of distribution and use, see license.
44
// Created by: Alexey Gamzov
@@ -9,6 +9,7 @@
99
using System.Diagnostics;
1010
using System.Reflection;
1111
using System.Runtime.Serialization;
12+
using System.Security;
1213
using System.Text;
1314
using System.Threading;
1415
using Xtensive.Collections;
@@ -25,18 +26,20 @@ namespace Xtensive.Core
2526
/// </summary>
2627
[Serializable]
2728
public abstract class AssociateProvider :
28-
IDeserializationCallback
29+
IDeserializationCallback,
30+
ISerializable
2931
{
3032
private static readonly AsyncLocal<SetSlim<TypePair>> inProgressAsync = new AsyncLocal<SetSlim<TypePair>>();
3133

3234
private static SetSlim<TypePair> InProgress
3335
{
3436
get {
35-
if (inProgressAsync.Value==null)
37+
if (inProgressAsync.Value == null) {
3638
inProgressAsync.Value = new SetSlim<TypePair>();
39+
}
3740
return inProgressAsync.Value;
3841
}
39-
set { inProgressAsync.Value = value; }
42+
set => inProgressAsync.Value = value;
4043
}
4144

4245
[NonSerialized]
@@ -55,19 +58,20 @@ private static SetSlim<TypePair> InProgress
5558
protected object[] ConstructorParams
5659
{
5760
[DebuggerStepThrough]
58-
get { return constructorParams; }
61+
get => constructorParams;
5962
[DebuggerStepThrough]
60-
set { constructorParams = value; }
63+
set => constructorParams = value;
6164
}
6265

6366
/// <summary>
6467
/// Gets or sets associate type suffixes.
6568
/// </summary>
66-
protected string[] TypeSuffixes {
69+
protected string[] TypeSuffixes
70+
{
6771
[DebuggerStepThrough]
68-
get { return typeSuffixes; }
72+
get => typeSuffixes;
6973
[DebuggerStepThrough]
70-
set { typeSuffixes = value; }
74+
set => typeSuffixes = value;
7175
}
7276

7377
/// <summary>
@@ -91,10 +95,12 @@ protected void AddHighPriorityLocation(Assembly assembly, string nameSpace, bool
9195
{
9296
lock (_lock) {
9397
var newHighPriorityLocations = new List<Pair<Assembly, string>>(highPriorityLocations);
94-
if (overriding)
98+
if (overriding) {
9599
newHighPriorityLocations.Insert(0, new Pair<Assembly, string>(assembly, nameSpace));
96-
else
100+
}
101+
else {
97102
newHighPriorityLocations.Add(new Pair<Assembly, string>(assembly, nameSpace));
103+
}
98104
Thread.MemoryBarrier();
99105
highPriorityLocations = newHighPriorityLocations;
100106
}
@@ -103,10 +109,7 @@ protected void AddHighPriorityLocation(Assembly assembly, string nameSpace, bool
103109
/// <summary>
104110
/// Gets a list of high priority locations.
105111
/// </summary>
106-
protected List<Pair<Assembly, string>> HighPriorityLocations
107-
{
108-
get { return highPriorityLocations; }
109-
}
112+
protected List<Pair<Assembly, string>> HighPriorityLocations => highPriorityLocations;
110113

111114
/// <summary>
112115
/// Gets associate instance for specified parameter and result types.
@@ -120,11 +123,9 @@ protected List<Pair<Assembly, string>> HighPriorityLocations
120123
protected TResult GetAssociate<TKey, TAssociate, TResult>()
121124
where TAssociate : class
122125
{
123-
var key = new TypePair(typeof (TKey), typeof (TResult));
124-
return (TResult) cache.GetValue(key, _key => {
125-
Type foundFor;
126-
return ConvertAssociate<TKey, TAssociate, TResult>(CreateAssociate<TKey, TAssociate>(out foundFor));
127-
});
126+
var key = new TypePair(typeof(TKey), typeof(TResult));
127+
return (TResult) cache.GetValue(key,
128+
_key => ConvertAssociate<TKey, TAssociate, TResult>(CreateAssociate<TKey, TAssociate>(out var foundFor)));
128129
}
129130

130131
/// <summary>
@@ -141,30 +142,22 @@ protected TResult GetAssociate<TKey, TAssociate, TResult>()
141142
protected TResult GetAssociate<TKey1, TKey2, TAssociate, TResult>()
142143
where TAssociate : class
143144
{
144-
var key = new TypePair(typeof (TKey1), typeof (TResult));
145+
var key = new TypePair(typeof(TKey1), typeof(TResult));
145146
return (TResult) cache.GetValue(key, _key => {
146-
Type foundFor;
147-
TAssociate associate1 = CreateAssociate<TKey1, TAssociate>(out foundFor);
148-
TAssociate associate2 = CreateAssociate<TKey2, TAssociate>(out foundFor);
147+
var associate1 = CreateAssociate<TKey1, TAssociate>(out var foundFor);
148+
var associate2 = CreateAssociate<TKey2, TAssociate>(out foundFor);
149149
// Preferring non-null ;)
150-
TAssociate associate;
151-
if (associate1==null)
152-
associate = associate2;
153-
else if (associate2==null)
154-
associate = associate1;
155-
else
156-
// Both are non-null; preferring one of two
157-
associate = PreferAssociate<TKey1, TKey2, TAssociate>(associate1, associate2);
158-
if (associate==null) {
150+
var associate = associate1 ?? associate2 ?? PreferAssociate<TKey1, TKey2, TAssociate>(associate1, associate2);
151+
if (associate == null) {
159152
// Try to get complex associate (create it manually)
160153
associate = CreateCustomAssociate<TKey1, TKey2, TAssociate>();
161-
if (associate==null) {
154+
if (associate == null) {
162155
var stringBuilder = new StringBuilder();
163-
for (int i = 0; i < TypeSuffixes.Length; i++) {
164-
if (i!=0) {
165-
stringBuilder.Append(", ");
156+
for (var i = 0; i < TypeSuffixes.Length; i++) {
157+
if (i != 0) {
158+
_ = stringBuilder.Append(", ");
166159
}
167-
stringBuilder.Append(TypeSuffixes[i]);
160+
_ = stringBuilder.Append(TypeSuffixes[i]);
168161
}
169162
throw new InvalidOperationException(string.Format(
170163
Strings.ExCantFindAssociate2, stringBuilder,
@@ -189,12 +182,9 @@ protected TResult GetAssociate<TKey1, TKey2, TAssociate, TResult>()
189182
protected virtual TAssociate PreferAssociate<TKey1, TKey2, TAssociate>(TAssociate associate1,
190183
TAssociate associate2)
191184
{
192-
int locationPosition1 = GetAssociateLocationPosition(associate1);
193-
int locationPosition2 = GetAssociateLocationPosition(associate2);
194-
if (locationPosition1 <= locationPosition2)
195-
return associate1;
196-
else
197-
return associate2;
185+
var locationPosition1 = GetAssociateLocationPosition(associate1);
186+
var locationPosition2 = GetAssociateLocationPosition(associate2);
187+
return locationPosition1 <= locationPosition2 ? associate1 : associate2;
198188
}
199189

200190
/// <summary>
@@ -211,9 +201,11 @@ protected int GetAssociateLocationPosition<TAssociate>(TAssociate associate)
211201
associate.GetType().Assembly,
212202
associate.GetType().Namespace);
213203
var hpl = HighPriorityLocations;
214-
for (int i = 0; i < hpl.Count; i++)
215-
if (AdvancedComparerStruct<Pair<Assembly, string>>.Default.Equals(hpl[i], entry))
204+
for (var i = 0; i < hpl.Count; i++) {
205+
if (AdvancedComparerStruct<Pair<Assembly, string>>.Default.Equals(hpl[i], entry)) {
216206
return i;
207+
}
208+
}
217209
return int.MaxValue;
218210
}
219211

@@ -229,19 +221,22 @@ protected int GetAssociateLocationPosition<TAssociate>(TAssociate associate)
229221
protected virtual TAssociate CreateAssociate<TKey, TAssociate>(out Type foundFor)
230222
where TAssociate : class
231223
{
232-
if (InProgress==null)
224+
if (InProgress == null) {
233225
InProgress = new SetSlim<TypePair>();
234-
var progressionMark = new TypePair(typeof (TKey), typeof (TAssociate));
235-
if (InProgress.Contains(progressionMark))
226+
}
227+
228+
var progressionMark = new TypePair(typeof(TKey), typeof(TAssociate));
229+
if (InProgress.Contains(progressionMark)) {
236230
throw new InvalidOperationException(Strings.ExRecursiveAssociateLookupDetected);
237-
InProgress.Add(progressionMark);
231+
}
232+
_ = InProgress.Add(progressionMark);
238233
try {
239234
var associate = TypeHelper.CreateAssociate<TAssociate>(
240-
typeof (TKey), out foundFor, TypeSuffixes, constructorParams, highPriorityLocations);
235+
typeof(TKey), out foundFor, TypeSuffixes, constructorParams, highPriorityLocations);
241236
return associate;
242237
}
243238
finally {
244-
InProgress.Remove(progressionMark);
239+
_ = InProgress.Remove(progressionMark);
245240
}
246241
}
247242

@@ -255,9 +250,7 @@ protected virtual TAssociate CreateAssociate<TKey, TAssociate>(out Type foundFor
255250
/// <returns>Associate instance or <see langword="null"/>.</returns>
256251
protected virtual TAssociate CreateCustomAssociate<TKey1, TKey2, TAssociate>()
257252
where TAssociate : class
258-
{
259-
return null;
260-
}
253+
=> null;
261254

262255
/// <summary>
263256
/// Converts <paramref name="associate"/> to <typeparamref name="TResult"/> object.
@@ -268,9 +261,7 @@ protected virtual TAssociate CreateCustomAssociate<TKey1, TKey2, TAssociate>()
268261
/// <param name="associate">Associate to convert to result.</param>
269262
/// <returns>Conversion result.</returns>
270263
protected virtual TResult ConvertAssociate<TKey, TAssociate, TResult>(TAssociate associate)
271-
{
272-
return (TResult) (object) associate;
273-
}
264+
=> (TResult) (object) associate;
274265

275266
/// <summary>
276267
/// Converts <paramref name="associate"/> to <typeparamref name="TResult"/> object.
@@ -282,9 +273,7 @@ protected virtual TResult ConvertAssociate<TKey, TAssociate, TResult>(TAssociate
282273
/// <param name="associate">Associate to convert to result.</param>
283274
/// <returns>Conversion result.</returns>
284275
protected virtual TResult ConvertAssociate<TKey1, TKey2, TAssociate, TResult>(TAssociate associate)
285-
{
286-
return (TResult) (object) associate;
287-
}
276+
=> (TResult) (object) associate;
288277

289278

290279
// Constructors
@@ -294,11 +283,28 @@ protected virtual TResult ConvertAssociate<TKey1, TKey2, TAssociate, TResult>(TA
294283
/// </summary>
295284
protected AssociateProvider()
296285
{
297-
constructorParams = new object[] {this};
286+
constructorParams = new object[] { this };
298287
_lock = new object();
299288
cache = ThreadSafeDictionary<TypePair, object>.Create(_lock);
300289
}
301290

291+
protected AssociateProvider(SerializationInfo info, StreamingContext context)
292+
{
293+
if (info == null) {
294+
throw new ArgumentNullException(nameof(info));
295+
}
296+
297+
var constructorParamsExceptThis = (object[]) info.GetValue(nameof(constructorParams), typeof(object[]));
298+
constructorParams = new object[constructorParamsExceptThis.Length + 1];
299+
constructorParams[0] = this;
300+
Array.Copy(constructorParamsExceptThis, 0, constructorParams, 1, constructorParamsExceptThis.Length);
301+
302+
typeSuffixes = (string[]) info.GetValue(nameof(typeSuffixes), typeof(string[]));
303+
304+
var highPriorityLocationsSerializable = (List<Pair<string, string>>) info.GetValue(nameof(highPriorityLocations), typeof(List<Pair<string, string>>));
305+
highPriorityLocations = highPriorityLocationsSerializable.SelectToList(ls => new Pair<Assembly, string>(Assembly.Load(ls.First), ls.Second));
306+
}
307+
302308
/// <summary>
303309
/// Performs post-deserialization actions.
304310
/// </summary>
@@ -308,5 +314,25 @@ public virtual void OnDeserialization(object sender)
308314
_lock = new object();
309315
cache = ThreadSafeDictionary<TypePair, object>.Create(_lock);
310316
}
317+
318+
/// <inheritdoc/>
319+
[SecurityCritical]
320+
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
321+
{
322+
object[] constructorParamsExceptThis = null;
323+
// need to exclude this form parameters to prevent loop
324+
if (constructorParams.Length == 1) {
325+
constructorParamsExceptThis = Array.Empty<object>();
326+
}
327+
else {
328+
constructorParamsExceptThis = new object[constructorParams.Length - 1];
329+
Array.Copy(constructorParams, 1, constructorParamsExceptThis, 0, constructorParamsExceptThis.Length);
330+
}
331+
info.AddValue(nameof(constructorParams), constructorParamsExceptThis, constructorParams.GetType());
332+
info.AddValue(nameof(typeSuffixes), typeSuffixes, typeSuffixes.GetType());
333+
334+
var highPriorityLocationsSerializable = highPriorityLocations.SelectToList(l => new Pair<string, string>(l.First.FullName, l.Second));
335+
info.AddValue(nameof(highPriorityLocations), highPriorityLocationsSerializable, highPriorityLocationsSerializable.GetType());
336+
}
311337
}
312338
}

Orm/Xtensive.Orm/Core/MethodCacheBase.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// Copyright (C) 2003-2010 Xtensive LLC.
2-
// All rights reserved.
3-
// For conditions of distribution and use, see license.
1+
// Copyright (C) 2008-2021 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
44
// Created by: Alex Yakunin
55
// Created: 2008.02.10
66

@@ -44,7 +44,7 @@ public MethodCacheBase(TImplementation implementation)
4444
/// <param name="context"></param>
4545
protected MethodCacheBase(SerializationInfo info, StreamingContext context)
4646
{
47-
Implementation = (TImplementation)info.GetValue("Implementation", typeof(TImplementation));
47+
Implementation = (TImplementation) info.GetValue("Implementation", typeof(TImplementation));
4848
}
4949

5050
/// <summary>
@@ -55,7 +55,7 @@ protected MethodCacheBase(SerializationInfo info, StreamingContext context)
5555
[SecurityCritical]
5656
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
5757
{
58-
info.AddValue("Implementation", Implementation);
58+
info.AddValue("Implementation", Implementation, Implementation.GetType());
5959
}
6060
}
6161
}

0 commit comments

Comments
 (0)