forked from nhibernate/nhibernate-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPropertyFactory.cs
148 lines (132 loc) · 4.99 KB
/
PropertyFactory.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
using System;
using System.Reflection;
using NHibernate.Engine;
using NHibernate.Id;
using NHibernate.Mapping;
using NHibernate.Properties;
using NHibernate.Type;
using NHibernate.Util;
namespace NHibernate.Tuple
{
/// <summary>
/// Responsible for generation of runtime metamodel <see cref="NHibernate.Tuple.Property" /> representations.
/// Makes distinction between identifier, version, and other (standard) properties.
/// </summary>
/// <remarks>
/// Author: Steve Ebersole
/// </remarks>
public class PropertyFactory
{
/// <summary>
/// Generates an IdentifierProperty representation of the for a given entity mapping.
/// </summary>
/// <param name="mappedEntity">The mapping definition of the entity.</param>
/// <param name="generator">The identifier value generator to use for this identifier.</param>
/// <returns>The appropriate IdentifierProperty definition.</returns>
public static IdentifierProperty BuildIdentifierProperty(PersistentClass mappedEntity, IIdentifierGenerator generator)
{
string mappedUnsavedValue = mappedEntity.Identifier.NullValue;
IType type = mappedEntity.Identifier.Type;
Mapping.Property property = mappedEntity.IdentifierProperty;
IdentifierValue unsavedValue = UnsavedValueFactory.GetUnsavedIdentifierValue(mappedUnsavedValue, GetGetter(property), type, GetConstructor(mappedEntity));
if (property == null)
{
// this is a virtual id property...
return new IdentifierProperty(type, mappedEntity.HasEmbeddedIdentifier,
mappedEntity.HasIdentifierMapper, unsavedValue, generator);
}
else
{
return new IdentifierProperty(property.Name, type, mappedEntity.HasEmbeddedIdentifier, unsavedValue, generator);
}
}
/// <summary>
/// Generates a VersionProperty representation for an entity mapping given its
/// version mapping Property.
/// </summary>
/// <param name="property">The version mapping Property.</param>
/// <param name="lazyAvailable">Is property lazy loading currently available.</param>
/// <returns>The appropriate VersionProperty definition.</returns>
public static VersionProperty BuildVersionProperty(Mapping.Property property, bool lazyAvailable)
{
String mappedUnsavedValue = ((IKeyValue) property.Value).NullValue;
VersionValue unsavedValue = UnsavedValueFactory.GetUnsavedVersionValue(
mappedUnsavedValue,
GetGetter(property),
(IVersionType) property.Type,
GetConstructor(property.PersistentClass)
);
bool lazy = lazyAvailable && property.IsLazy;
return new VersionProperty(
property.Name,
property.Value.Type,
lazy,
property.IsInsertable,
property.IsUpdateable,
property.Generation == PropertyGeneration.Insert || property.Generation == PropertyGeneration.Always,
property.Generation == PropertyGeneration.Always,
property.IsOptional,
property.IsUpdateable && !lazy,
property.IsOptimisticLocked,
property.CascadeStyle,
unsavedValue
);
}
/// <summary>
/// Generate a "standard" (i.e., non-identifier and non-version) based on the given
/// mapped property.
/// </summary>
/// <param name="property">The mapped property.</param>
/// <param name="lazyAvailable">Is property lazy loading currently available.</param>
/// <returns>The appropriate StandardProperty definition.</returns>
public static StandardProperty BuildStandardProperty(Mapping.Property property, bool lazyAvailable)
{
IType type = property.Value.Type;
// we need to dirty check collections, since they can cause an owner
// version number increment
// we need to dirty check many-to-ones with not-found="ignore" in order
// to update the cache (not the database), since in this case a null
// entity reference can lose information
bool alwaysDirtyCheck = type.IsAssociationType &&
((IAssociationType) type).IsAlwaysDirtyChecked;
return new StandardProperty(
property.Name,
type,
lazyAvailable && property.IsLazy,
property.IsInsertable,
property.IsUpdateable,
property.Generation == PropertyGeneration.Insert || property.Generation == PropertyGeneration.Always,
property.Generation == PropertyGeneration.Always,
property.IsOptional,
alwaysDirtyCheck || property.IsUpdateable,
property.IsOptimisticLocked,
property.CascadeStyle,
property.Value.FetchMode
);
}
private static ConstructorInfo GetConstructor(PersistentClass persistentClass)
{
if (persistentClass == null || !persistentClass.HasPocoRepresentation)
{
return null;
}
try
{
return ReflectHelper.GetDefaultConstructor(persistentClass.MappedClass);
}
catch
{
return null;
}
}
private static IGetter GetGetter(Mapping.Property mappingProperty)
{
if (mappingProperty == null || !mappingProperty.PersistentClass.HasPocoRepresentation)
{
return null;
}
IPropertyAccessor pa = PropertyAccessorFactory.GetPropertyAccessor(mappingProperty, EntityMode.Poco);
return pa.GetGetter(mappingProperty.PersistentClass.MappedClass, mappingProperty.Name);
}
}
}