Skip to content

Commit da22ea2

Browse files
authored
Optimize FieldAccessor (#335)
undefined
1 parent feb0100 commit da22ea2

9 files changed

+99
-173
lines changed

Orm/Xtensive.Orm/Orm/Internals/FieldAccessor.cs

+12-29
Original file line numberDiff line numberDiff line change
@@ -4,40 +4,23 @@
44
// Created by: Alex Yakunin
55
// Created: 2010.02.19
66

7-
using System;
8-
using System.Diagnostics;
97
using Xtensive.Core;
108
using Xtensive.Orm.Model;
119

12-
namespace Xtensive.Orm.Internals
13-
{
14-
internal abstract class FieldAccessor
15-
{
16-
private FieldInfo fld;
17-
18-
public FieldInfo Field {
19-
get { return fld; }
20-
set {
21-
if (fld !=null)
22-
throw Exceptions.AlreadyInitialized("Field");
23-
fld = value;
24-
}
25-
}
26-
27-
public object DefaultUntypedValue { get; private set; }
28-
29-
public abstract bool AreSameValues(object oldValue, object newValue);
10+
namespace Xtensive.Orm.Internals;
3011

31-
public abstract void SetUntypedValue(Persistent obj, object value);
32-
33-
public abstract object GetUntypedValue(Persistent obj);
12+
internal abstract class FieldAccessor(object defaultUntypedValue)
13+
{
14+
protected ColNum FieldIndex;
3415

16+
public object DefaultUntypedValue { get; } = defaultUntypedValue;
3517

36-
// Constructors
37-
38-
protected FieldAccessor(object defaultUntypedValue)
39-
{
40-
DefaultUntypedValue = defaultUntypedValue;
41-
}
18+
public virtual void SetFieldInfo(FieldInfo value)
19+
{
20+
FieldIndex = FieldIndex == 0 ? value.MappingInfo.Offset : throw Exceptions.AlreadyInitialized("Field");
4221
}
22+
23+
public abstract bool AreSameValues(object oldValue, object newValue);
24+
public abstract void SetUntypedValue(Persistent obj, object value);
25+
public abstract object GetUntypedValue(Persistent obj);
4326
}

Orm/Xtensive.Orm/Orm/Internals/FieldAccessorProvider.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ private static FieldAccessor CreateFieldAccessor(Type accessorType, FieldInfo fi
5656
accessorType.CachedMakeGenericType(field.ValueType),
5757
BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
5858
null, Array.Empty<object>(), null);
59-
accessor.Field = field;
59+
accessor.SetFieldInfo(field);
6060
return accessor;
6161
}
6262
}
63-
}
63+
}

Orm/Xtensive.Orm/Orm/Internals/FieldAccessors/CachingFieldAccessor.cs

+13-12
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,21 @@
44
// Created by: Dmitri Maximov
55
// Created: 2009.07.08
66

7-
using System;
7+
using Xtensive.Core;
88
using Xtensive.Orm.Model;
99

10-
namespace Xtensive.Orm.Internals.FieldAccessors
10+
namespace Xtensive.Orm.Internals.FieldAccessors;
11+
12+
internal abstract class CachingFieldAccessor<T> : FieldAccessor<T>
1113
{
12-
internal abstract class CachingFieldAccessor<T> : FieldAccessor<T>
13-
{
14-
public static Func<Persistent, FieldInfo, IFieldValueAdapter> Constructor;
14+
public static Func<Persistent, FieldInfo, IFieldValueAdapter> Constructor;
15+
16+
protected FieldInfo Field;
1517

16-
public override T GetValue(Persistent obj)
17-
{
18-
var field = Field;
19-
var valueAdapter = obj.GetFieldValueAdapter(field, Constructor);
20-
return (T) valueAdapter;
21-
}
18+
public override void SetFieldInfo(FieldInfo value) {
19+
Field = Field is null ? value : throw Exceptions.AlreadyInitialized("Field");
20+
base.SetFieldInfo(value);
2221
}
23-
}
22+
23+
public override T GetValue(Persistent obj) => (T) obj.GetFieldValueAdapter(Field, Constructor);
24+
}

Orm/Xtensive.Orm/Orm/Internals/FieldAccessors/DefaultFieldAccessor.cs

+2-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
// Created by: Alexey Gamzov
55
// Created: 2008.05.26
66

7-
using System;
87
using Xtensive.Reflection;
98

109
namespace Xtensive.Orm.Internals.FieldAccessors
@@ -32,17 +31,11 @@ public override bool AreSameValues(object oldValue, object newValue)
3231
}
3332

3433
/// <inheritdoc/>
35-
public override T GetValue(Persistent obj)
36-
{
37-
var fieldIndex = Field.MappingInfo.Offset;
38-
var tuple = obj.Tuple;
39-
var value = tuple.GetValueOrDefault<T>(fieldIndex);
40-
return value;
41-
}
34+
public override T GetValue(Persistent obj) => obj.Tuple.GetValueOrDefault<T>(FieldIndex);
4235

4336
/// <inheritdoc/>
4437
/// <exception cref="InvalidOperationException">Invalid arguments.</exception>
4538
public override void SetValue(Persistent obj, T value) =>
46-
obj.Tuple.SetValue(Field.MappingInfo.Offset, value);
39+
obj.Tuple.SetValue(FieldIndex, value);
4740
}
4841
}

Orm/Xtensive.Orm/Orm/Internals/FieldAccessors/EntityFieldAccessor.cs

+24-30
Original file line numberDiff line numberDiff line change
@@ -4,54 +4,48 @@
44
// Created by: Alexey Gamzov
55
// Created: 2008.05.26
66

7-
using System;
8-
7+
using Xtensive.Core;
8+
using Xtensive.Orm.Model;
99
using Xtensive.Tuples;
1010

1111
namespace Xtensive.Orm.Internals.FieldAccessors
1212
{
1313
internal class EntityFieldAccessor<T> : FieldAccessor<T>
1414
{
15-
/// <inheritdoc/>
16-
public override bool AreSameValues(object oldValue, object newValue)
15+
private FieldInfo field;
16+
17+
public override void SetFieldInfo(FieldInfo value)
1718
{
18-
return ReferenceEquals(oldValue, newValue);
19+
field = field is null ? value : throw Exceptions.AlreadyInitialized("Field");
20+
base.SetFieldInfo(value);
1921
}
22+
23+
/// <inheritdoc/>
24+
public override bool AreSameValues(object oldValue, object newValue) => ReferenceEquals(oldValue, newValue);
2025
/// <inheritdoc/>
2126
/// <exception cref="InvalidOperationException">Invalid arguments.</exception>
2227
public override void SetValue(Persistent obj, T value)
2328
{
24-
var entity = value as Entity;
25-
var field = Field;
29+
var tuple = obj.Tuple;
30+
if (value is Entity entity) {
31+
if (entity.Session != obj.Session)
32+
throw new InvalidOperationException(string.Format(Strings.ExEntityXIsBoundToAnotherSession, entity.Key));
2633

27-
if (!ReferenceEquals(value, null) && entity==null)
28-
throw new InvalidOperationException(string.Format(
29-
Strings.ExValueShouldBeXDescendant, WellKnownOrmTypes.Entity));
30-
31-
if (entity!=null && entity.Session!=obj.Session)
32-
throw new InvalidOperationException(string.Format(
33-
Strings.ExEntityXIsBoundToAnotherSession, entity.Key));
34-
35-
var mappingInfo = field.MappingInfo;
36-
int fieldIndex = mappingInfo.Offset;
37-
if (entity==null) {
38-
int nextFieldIndex = fieldIndex + mappingInfo.Length;
39-
for (int i = fieldIndex; i < nextFieldIndex; i++)
40-
obj.Tuple.SetValue(i, null);
34+
entity.Key.Value.CopyTo(tuple, 0, FieldIndex, field.MappingInfo.Length);
4135
}
4236
else {
43-
entity.Key.Value.CopyTo(obj.Tuple, 0, fieldIndex, mappingInfo.Length);
37+
if (!ReferenceEquals(value, null))
38+
throw new InvalidOperationException(string.Format(Strings.ExValueShouldBeXDescendant, WellKnownOrmTypes.Entity));
39+
40+
for (int i = FieldIndex, nextFieldIndex = FieldIndex + field.MappingInfo.Length; i < nextFieldIndex; i++)
41+
tuple.SetValue(i, null);
4442
}
4543
}
4644

4745
/// <inheritdoc/>
48-
public override T GetValue(Persistent obj)
49-
{
50-
var field = Field;
51-
Key key = obj.GetReferenceKey(field);
52-
if (key is null)
53-
return default(T);
54-
return (T) (object) obj.Session.Query.SingleOrDefault(key);
55-
}
46+
public override T GetValue(Persistent obj) =>
47+
obj.GetReferenceKey(field) is { } key
48+
? (T) (object) obj.Session.Query.SingleOrDefault(key)
49+
: default;
5650
}
5751
}

Orm/Xtensive.Orm/Orm/Internals/FieldAccessors/EnumFieldAccessor.cs

+15-15
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Created by: Alexey Gamzov
55
// Created: 2008.06.07
66

7-
using System;
7+
using Xtensive.Orm.Model;
88
using Xtensive.Reflection;
99
using Xtensive.Tuples;
1010

@@ -18,6 +18,14 @@ internal sealed class EnumFieldAccessor<T> : FieldAccessor<T>
1818
? (type.IsNullable() ? null : Enum.GetValues(type).GetValue(0))
1919
: default(T);
2020

21+
private Type columnValueType;
22+
23+
public override void SetFieldInfo(FieldInfo value)
24+
{
25+
columnValueType = value.Column.ValueType;
26+
base.SetFieldInfo(value);
27+
}
28+
2129
/// <inheritdoc/>
2230
public override bool AreSameValues(object oldValue, object newValue)
2331
{
@@ -27,25 +35,17 @@ public override bool AreSameValues(object oldValue, object newValue)
2735
/// <inheritdoc/>
2836
public override T GetValue(Persistent obj)
2937
{
30-
var field = Field;
31-
int fieldIndex = field.MappingInfo.Offset;
32-
var tuple = obj.Tuple;
33-
34-
TupleFieldState state;
35-
var value = tuple.GetValue(fieldIndex, out state);
36-
if (!state.HasValue())
37-
return (T) @default;
38-
if (type.IsEnum)
39-
return (T) Enum.ToObject(type, value);
40-
return (T) Enum.ToObject(Nullable.GetUnderlyingType(type), value);
38+
var value = obj.Tuple.GetValue(FieldIndex, out var state);
39+
return (T) (!state.HasValue() ? @default
40+
: type.IsEnum ? Enum.ToObject(type, value)
41+
: Enum.ToObject(Nullable.GetUnderlyingType(type), value));
4142
}
4243

4344
/// <inheritdoc/>
4445
public override void SetValue(Persistent obj, T value)
4546
{
46-
var field = Field;
4747
// Biconverter<object, T> converter = GetConverter(field.ValueType);
48-
obj.Tuple.SetValue(field.MappingInfo.Offset, value==null ? null : Convert.ChangeType(value, field.Column.ValueType));
48+
obj.Tuple.SetValue(FieldIndex, value==null ? null : Convert.ChangeType(value, columnValueType));
4949
}
5050
}
51-
}
51+
}

Orm/Xtensive.Orm/Orm/Internals/FieldAccessors/KeyFieldAccessor.cs

+17-31
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,27 @@
44
// Created by: Alex Yakunin
55
// Created: 2008.11.21
66

7-
using System;
87
using Xtensive.Tuples;
9-
using Tuple = Xtensive.Tuples.Tuple;
108

11-
namespace Xtensive.Orm.Internals.FieldAccessors
12-
{
13-
internal class KeyFieldAccessor<T> : FieldAccessor<T>
14-
{
15-
private static readonly T @default = default;
9+
namespace Xtensive.Orm.Internals.FieldAccessors;
1610

17-
/// <inheritdoc/>
18-
public override bool AreSameValues(object oldValue, object newValue)
19-
{
20-
return object.Equals(oldValue, newValue);
21-
}
11+
internal class KeyFieldAccessor<T> : FieldAccessor<T>
12+
{
13+
/// <inheritdoc/>
14+
public override bool AreSameValues(object oldValue, object newValue) => Equals(oldValue, newValue);
2215

23-
/// <inheritdoc/>
24-
public override T GetValue(Persistent obj)
25-
{
26-
var field = Field;
27-
int fieldIndex = field.MappingInfo.Offset;
28-
var tuple = obj.Tuple;
29-
TupleFieldState state;
30-
var value = tuple.GetValue<string>(fieldIndex, out state);
31-
if (!state.IsAvailable())
32-
return @default;
33-
return (T) (object) Key.Parse(obj.Session.Domain, value);
34-
}
16+
/// <inheritdoc/>
17+
public override T GetValue(Persistent obj)
18+
{
19+
var value = obj.Tuple.GetValue<string>(FieldIndex, out var state);
20+
return !state.IsAvailable()
21+
? default
22+
: (T) (object) Key.Parse(obj.Session.Domain, value);
23+
}
3524

36-
/// <inheritdoc/>
37-
public override void SetValue(Persistent obj, T value)
38-
{
39-
var field = Field;
40-
var key = (Key) (object) value;
41-
obj.Tuple.SetValue(field.MappingInfo.Offset, key is null ? null : key.Format());
42-
}
25+
/// <inheritdoc/>
26+
public override void SetValue(Persistent obj, T value)
27+
{
28+
obj.Tuple.SetValue(FieldIndex, ((Key) (object) value)?.Format());
4329
}
4430
}

Orm/Xtensive.Orm/Orm/Internals/FieldAccessors/StructureFieldAccessor.cs

+7-14
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,28 @@
44
// Created by: Dmitri Maximov
55
// Created: 2008.05.30
66

7-
using System;
8-
using Xtensive.Core;
9-
107
using Xtensive.Tuples;
118

129
namespace Xtensive.Orm.Internals.FieldAccessors
1310
{
1411
internal sealed class StructureFieldAccessor<T> : CachingFieldAccessor<T>
1512
{
1613
/// <inheritdoc/>
17-
public override bool AreSameValues(object oldValue, object newValue)
18-
{
19-
return oldValue.Equals(newValue);
20-
}
14+
public override bool AreSameValues(object oldValue, object newValue) => oldValue.Equals(newValue);
15+
2116
/// <inheritdoc/>
2217
public override void SetValue(Persistent obj, T value)
2318
{
24-
var field = Field;
2519
ArgumentNullException.ThrowIfNull(value);
2620
var valueType = value.GetType();
27-
if (field.ValueType != valueType)
21+
if (Field.ValueType != valueType)
2822
throw new InvalidOperationException(String.Format(
29-
Strings.ExResultTypeIncorrect, valueType.Name, field.ValueType.Name));
23+
Strings.ExResultTypeIncorrect, valueType.Name, Field.ValueType.Name));
3024

3125
var structure = (Structure) (object) value;
3226
var adapter = (IFieldValueAdapter)value;
33-
if (adapter.Owner!=null)
34-
adapter.Owner.EnsureIsFetched(adapter.Field);
35-
structure.Tuple.CopyTo(obj.Tuple, 0, field.MappingInfo.Offset, field.MappingInfo.Length);
27+
adapter.Owner?.EnsureIsFetched(adapter.Field);
28+
structure.Tuple.CopyTo(obj.Tuple, 0, FieldIndex, Field.MappingInfo.Length);
3629
}
3730

3831
// Type initializer
@@ -42,4 +35,4 @@ static StructureFieldAccessor()
4235
Constructor = (obj, field) => Activator.CreateStructure(field.ValueType, obj, field);
4336
}
4437
}
45-
}
38+
}

0 commit comments

Comments
 (0)