From 22165b009bbf690d6ac6887b9377c3e07e4e872e Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Thu, 28 Dec 2017 09:53:17 -0700 Subject: [PATCH 1/4] Eliminate usage of protected field uniqueKeyPropertyName. --- src/NHibernate/Async/Type/EntityType.cs | 6 +++--- src/NHibernate/Type/EntityType.cs | 26 ++++++++++++++++--------- src/NHibernate/Type/ManyToOneType.cs | 2 +- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/NHibernate/Async/Type/EntityType.cs b/src/NHibernate/Async/Type/EntityType.cs index 6e0e345b1bc..864d11c4dd2 100644 --- a/src/NHibernate/Async/Type/EntityType.cs +++ b/src/NHibernate/Async/Type/EntityType.cs @@ -65,12 +65,12 @@ protected internal async Task GetReferenceValueAsync(object value, ISess else { IEntityPersister entityPersister = session.Factory.GetEntityPersister(GetAssociatedEntityName()); - object propertyValue = entityPersister.GetPropertyValue(value, uniqueKeyPropertyName); + object propertyValue = entityPersister.GetPropertyValue(value, _uniqueKeyPropertyName); // We now have the value of the property-ref we reference. However, // we need to dig a little deeper, as that property might also be // an entity type, in which case we need to resolve its identitifier - IType type = entityPersister.GetPropertyType(uniqueKeyPropertyName); + IType type = entityPersister.GetPropertyType(_uniqueKeyPropertyName); if (type.IsEntityType) { propertyValue = await (((EntityType) type).GetReferenceValueAsync(propertyValue, session, cancellationToken)).ConfigureAwait(false); @@ -191,7 +191,7 @@ public override Task ResolveIdentifierAsync(object value, ISessionImplem } else { - return LoadByUniqueKeyAsync(GetAssociatedEntityName(), uniqueKeyPropertyName, value, session, cancellationToken); + return LoadByUniqueKeyAsync(GetAssociatedEntityName(), _uniqueKeyPropertyName, value, session, cancellationToken); } } } diff --git a/src/NHibernate/Type/EntityType.cs b/src/NHibernate/Type/EntityType.cs index 5b1e94f1307..60fcde67cd0 100644 --- a/src/NHibernate/Type/EntityType.cs +++ b/src/NHibernate/Type/EntityType.cs @@ -17,7 +17,11 @@ namespace NHibernate.Type [Serializable] public abstract partial class EntityType : AbstractType, IAssociationType { + // Since v5.1 + [Obsolete("This field has no more usages in NHibernate and will be removed. Use RHSUniqueKeyPropertyName instead.")] protected readonly string uniqueKeyPropertyName; + + private readonly string _uniqueKeyPropertyName; private readonly bool eager; private readonly string associatedEntityName; private readonly bool unwrapProxy; @@ -37,8 +41,12 @@ public abstract partial class EntityType : AbstractType, IAssociationType /// protected internal EntityType(string entityName, string uniqueKeyPropertyName, bool eager, bool unwrapProxy) { - associatedEntityName = entityName; +#pragma warning disable 618 this.uniqueKeyPropertyName = uniqueKeyPropertyName; +#pragma warning restore 618 + + associatedEntityName = entityName; + _uniqueKeyPropertyName = uniqueKeyPropertyName; this.eager = eager; this.unwrapProxy = unwrapProxy; } @@ -165,12 +173,12 @@ protected internal object GetReferenceValue(object value, ISessionImplementor se else { IEntityPersister entityPersister = session.Factory.GetEntityPersister(GetAssociatedEntityName()); - object propertyValue = entityPersister.GetPropertyValue(value, uniqueKeyPropertyName); + object propertyValue = entityPersister.GetPropertyValue(value, _uniqueKeyPropertyName); // We now have the value of the property-ref we reference. However, // we need to dig a little deeper, as that property might also be // an entity type, in which case we need to resolve its identitifier - IType type = entityPersister.GetPropertyType(uniqueKeyPropertyName); + IType type = entityPersister.GetPropertyType(_uniqueKeyPropertyName); if (type.IsEntityType) { propertyValue = ((EntityType) type).GetReferenceValue(propertyValue, session); @@ -283,7 +291,7 @@ public override sealed object NullSafeGet(DbDataReader rs, string[] names, ISess public bool IsUniqueKeyReference { - get { return uniqueKeyPropertyName != null; } + get { return _uniqueKeyPropertyName != null; } } public abstract bool IsNullable { get; } @@ -311,7 +319,7 @@ public IType GetIdentifierOrUniqueKeyType(IMapping factory) } else { - IType type = factory.GetReferencedPropertyType(GetAssociatedEntityName(), uniqueKeyPropertyName); + IType type = factory.GetReferencedPropertyType(GetAssociatedEntityName(), _uniqueKeyPropertyName); if (type.IsEntityType) { type = ((EntityType) type).GetIdentifierOrUniqueKeyType(factory); @@ -333,7 +341,7 @@ public string GetIdentifierOrUniqueKeyPropertyName(IMapping factory) } else { - return uniqueKeyPropertyName; + return _uniqueKeyPropertyName; } } @@ -399,7 +407,7 @@ public override object ResolveIdentifier(object value, ISessionImplementor sessi } else { - return LoadByUniqueKey(GetAssociatedEntityName(), uniqueKeyPropertyName, value, session); + return LoadByUniqueKey(GetAssociatedEntityName(), _uniqueKeyPropertyName, value, session); } } } @@ -438,7 +446,7 @@ public string LHSPropertyName public string RHSUniqueKeyPropertyName { - get { return uniqueKeyPropertyName; } + get { return _uniqueKeyPropertyName; } } public virtual string PropertyName @@ -472,7 +480,7 @@ public override int GetHashCode(object x, ISessionFactoryImplementor factory) public bool IsReferenceToPrimaryKey { - get { return string.IsNullOrEmpty(uniqueKeyPropertyName); } + get { return string.IsNullOrEmpty(_uniqueKeyPropertyName); } } public string GetOnCondition(string alias, ISessionFactoryImplementor factory, IDictionary enabledFilters) diff --git a/src/NHibernate/Type/ManyToOneType.cs b/src/NHibernate/Type/ManyToOneType.cs index 5f130dc8c35..b0e69c275b9 100644 --- a/src/NHibernate/Type/ManyToOneType.cs +++ b/src/NHibernate/Type/ManyToOneType.cs @@ -97,7 +97,7 @@ public override object Hydrate(DbDataReader rs, string[] names, ISessionImplemen private void ScheduleBatchLoadIfNeeded(object id, ISessionImplementor session) { //cannot batch fetch by unique key (property-ref associations) - if (uniqueKeyPropertyName == null && id != null) + if (RHSUniqueKeyPropertyName == null && id != null) { IEntityPersister persister = session.Factory.GetEntityPersister(GetAssociatedEntityName()); EntityKey entityKey = session.GenerateEntityKey(id, persister); From 73868e19662a506a9d053fc362ad7544e228c93f Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Thu, 7 Dec 2017 23:29:38 -0700 Subject: [PATCH 2/4] Don't throw then catch exception in Component if no componentClassName was set. --- src/NHibernate/Mapping/Component.cs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/NHibernate/Mapping/Component.cs b/src/NHibernate/Mapping/Component.cs index 3a4793d6458..33d5c3fee4d 100644 --- a/src/NHibernate/Mapping/Component.cs +++ b/src/NHibernate/Mapping/Component.cs @@ -133,26 +133,26 @@ public System.Type ComponentClass get { // NH Different implementation (we use reflection only when needed) - if (componentClass == null) + if (componentClass != null) return componentClass; + if (componentClassName == null) return null; + + try { - try - { - componentClass = ReflectHelper.ClassForName(componentClassName); - } - catch (Exception cnfe) - { - if (!IsDynamic) // TODO remove this if leave the Exception - throw new MappingException("component class not found: " + componentClassName, cnfe); - return null; - } + componentClass = ReflectHelper.ClassForName(componentClassName); + } + catch (Exception cnfe) + { + if (!IsDynamic) // TODO remove this if leave the Exception + throw new MappingException("component class not found: " + componentClassName, cnfe); + return null; } return componentClass; } set // TODO NH: Remove the setter { componentClass = value; - if (componentClass != null) - componentClassName = componentClass.AssemblyQualifiedName; + if (value != null) + componentClassName = value.AssemblyQualifiedName; } } From 629340b73e82e239d9a8c347ad5ba244b90e8c3f Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Sat, 4 Nov 2017 23:43:27 -0700 Subject: [PATCH 3/4] Implement helpers to serialize system types in preparation for .NET Core. Serialize System.Type, ConstructorInfo, FieldInfo, MethodInfo, and PropertyInfo using only basic types. --- .../Util/AssemblyQualifiedTypeName.cs | 39 ++--- src/NHibernate/Util/ReflectHelper.cs | 2 +- .../Util/SerializableConstructorInfo.cs | 81 ++++++++++ src/NHibernate/Util/SerializableFieldInfo.cs | 74 +++++++++ src/NHibernate/Util/SerializableMethodInfo.cs | 71 +++++++++ .../Util/SerializablePropertyInfo.cs | 74 +++++++++ src/NHibernate/Util/SerializableSystemType.cs | 145 ++++++++++++++++++ .../Util/SerializationInfoExtensions.cs | 14 ++ 8 files changed, 475 insertions(+), 25 deletions(-) create mode 100644 src/NHibernate/Util/SerializableConstructorInfo.cs create mode 100644 src/NHibernate/Util/SerializableFieldInfo.cs create mode 100644 src/NHibernate/Util/SerializableMethodInfo.cs create mode 100644 src/NHibernate/Util/SerializablePropertyInfo.cs create mode 100644 src/NHibernate/Util/SerializableSystemType.cs create mode 100644 src/NHibernate/Util/SerializationInfoExtensions.cs diff --git a/src/NHibernate/Util/AssemblyQualifiedTypeName.cs b/src/NHibernate/Util/AssemblyQualifiedTypeName.cs index b82fc677523..23c28469fff 100644 --- a/src/NHibernate/Util/AssemblyQualifiedTypeName.cs +++ b/src/NHibernate/Util/AssemblyQualifiedTypeName.cs @@ -2,35 +2,26 @@ namespace NHibernate.Util { + [Serializable] public class AssemblyQualifiedTypeName { - private readonly string type; - private readonly string assembly; - private readonly int hashCode; + private readonly string _type; + private readonly string _assembly; + private readonly int _hashCode; public AssemblyQualifiedTypeName(string type, string assembly) { - if (type == null) - { - throw new ArgumentNullException("type"); - } - this.type = type; - this.assembly = assembly; + _type = type ?? throw new ArgumentNullException(nameof(type)); + _assembly = assembly; unchecked { - hashCode = (type.GetHashCode() * 397) ^ (assembly != null ? assembly.GetHashCode() : 0); + _hashCode = (type.GetHashCode() * 397) ^ (assembly?.GetHashCode() ?? 0); } } - public string Type - { - get { return type; } - } + public string Type => _type; - public string Assembly - { - get { return assembly; } - } + public string Assembly => _assembly; public override bool Equals(object obj) { @@ -40,12 +31,12 @@ public override bool Equals(object obj) public override string ToString() { - if (assembly == null) + if (_assembly == null) { - return type; + return _type; } - return string.Concat(type, ", ", assembly); + return string.Concat(_type, ", ", _assembly); } public bool Equals(AssemblyQualifiedTypeName obj) @@ -58,12 +49,12 @@ public bool Equals(AssemblyQualifiedTypeName obj) { return true; } - return Equals(obj.type, type) && Equals(obj.assembly, assembly); + return Equals(obj._type, _type) && Equals(obj._assembly, _assembly); } public override int GetHashCode() { - return hashCode; + return _hashCode; } } -} \ No newline at end of file +} diff --git a/src/NHibernate/Util/ReflectHelper.cs b/src/NHibernate/Util/ReflectHelper.cs index b7b159025e6..9c7ef64f4c6 100644 --- a/src/NHibernate/Util/ReflectHelper.cs +++ b/src/NHibernate/Util/ReflectHelper.cs @@ -392,7 +392,7 @@ public static System.Type TypeFromAssembly(string type, string assembly, bool th /// type cannot be found then the assembly is loaded using /// . /// - public static System.Type TypeFromAssembly(AssemblyQualifiedTypeName name, bool throwOnError) + public static System.Type TypeFromAssembly(this AssemblyQualifiedTypeName name, bool throwOnError) { try { diff --git a/src/NHibernate/Util/SerializableConstructorInfo.cs b/src/NHibernate/Util/SerializableConstructorInfo.cs new file mode 100644 index 00000000000..abde74b5ad6 --- /dev/null +++ b/src/NHibernate/Util/SerializableConstructorInfo.cs @@ -0,0 +1,81 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Runtime.Serialization; +using System.Security; + +namespace NHibernate.Util +{ + [Serializable] + internal sealed class SerializableConstructorInfo : ISerializable, IEquatable + { + [NonSerialized] + private readonly ConstructorInfo _constructorInfo; + + /// + /// Creates a new instance of if + /// is not null, otherwise returns null. + /// + /// The being wrapped for serialization. + /// New instance of or null. + public static SerializableConstructorInfo Wrap(ConstructorInfo constructorInfo) + { + return constructorInfo == null ? null : new SerializableConstructorInfo(constructorInfo); + } + + /// + /// Creates a new + /// + /// The being wrapped for serialization. + private SerializableConstructorInfo(ConstructorInfo constructorInfo) + { + _constructorInfo = constructorInfo ?? throw new ArgumentNullException(nameof(constructorInfo)); + if (constructorInfo.DeclaringType == null) + { + throw new ArgumentException("ConstructorInfo must have non-null DeclaringType", nameof(constructorInfo)); + } + } + + private SerializableConstructorInfo(SerializationInfo info, StreamingContext context) + { + System.Type declaringType = info.GetValue("declaringType").GetSystemType(); + SerializableSystemType[] parameterSystemTypes = info.GetValue("parameterTypesHelper"); + + System.Type[] parameterTypes = parameterSystemTypes?.Select(x => x.GetSystemType()).ToArray() ?? new System.Type[0]; + _constructorInfo = declaringType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, parameterTypes, null); + + if (_constructorInfo == null) throw new MissingMethodException(declaringType.FullName, ".ctor"); + } + + [SecurityCritical] + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + SerializableSystemType[] parameterSystemTypes = + _constructorInfo.GetParameters() + .Select(x => SerializableSystemType.Wrap(x.ParameterType)) + .ToArray(); + + info.AddValue("declaringType", SerializableSystemType.Wrap(_constructorInfo.DeclaringType)); + info.AddValue("parameterTypesHelper", parameterSystemTypes); + } + + public ConstructorInfo Value => _constructorInfo; + + public bool Equals(SerializableConstructorInfo other) + { + return other != null && Equals(_constructorInfo, other._constructorInfo); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj is SerializableConstructorInfo && Equals((SerializableConstructorInfo) obj); + } + + public override int GetHashCode() + { + return (_constructorInfo != null ? _constructorInfo.GetHashCode() : 0); + } + } +} diff --git a/src/NHibernate/Util/SerializableFieldInfo.cs b/src/NHibernate/Util/SerializableFieldInfo.cs new file mode 100644 index 00000000000..30c3d3b5317 --- /dev/null +++ b/src/NHibernate/Util/SerializableFieldInfo.cs @@ -0,0 +1,74 @@ +using System; +using System.Reflection; +using System.Runtime.Serialization; +using System.Security; + +namespace NHibernate.Util +{ + [Serializable] + internal sealed class SerializableFieldInfo : ISerializable, IEquatable + { + [NonSerialized] + private readonly FieldInfo _fieldInfo; + + /// + /// Creates a new instance of if + /// is not null, otherwise returns null. + /// + /// The being wrapped for serialization. + /// New instance of or null. + public static SerializableFieldInfo Wrap(FieldInfo fieldInfo) + { + return fieldInfo == null ? null : new SerializableFieldInfo(fieldInfo); + } + + /// + /// Creates a new + /// + /// The being wrapped for serialization. + private SerializableFieldInfo(FieldInfo fieldInfo) + { + _fieldInfo = fieldInfo ?? throw new ArgumentNullException(nameof(fieldInfo)); + if (fieldInfo.IsStatic) throw new ArgumentException("Only for instance fields", nameof(fieldInfo)); + if (fieldInfo.DeclaringType == null) throw new ArgumentException("FieldInfo must have non-null DeclaringType", nameof(fieldInfo)); + } + + private SerializableFieldInfo(SerializationInfo info, StreamingContext context) + { + System.Type declaringType = info.GetValue("declaringType").GetSystemType(); + string fieldName = info.GetString("fieldName"); + + _fieldInfo = declaringType.GetField( + fieldName, + BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + + if (_fieldInfo == null) throw new MissingFieldException(declaringType.FullName, fieldName); + } + + [SecurityCritical] + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("declaringType", SerializableSystemType.Wrap(_fieldInfo.DeclaringType)); + info.AddValue("fieldName", _fieldInfo.Name); + } + + public FieldInfo Value => _fieldInfo; + + public bool Equals(SerializableFieldInfo other) + { + return other != null && Equals(_fieldInfo, other._fieldInfo); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj is SerializableFieldInfo && Equals((SerializableFieldInfo) obj); + } + + public override int GetHashCode() + { + return (_fieldInfo != null ? _fieldInfo.GetHashCode() : 0); + } + } +} diff --git a/src/NHibernate/Util/SerializableMethodInfo.cs b/src/NHibernate/Util/SerializableMethodInfo.cs new file mode 100644 index 00000000000..cdfc1767aba --- /dev/null +++ b/src/NHibernate/Util/SerializableMethodInfo.cs @@ -0,0 +1,71 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Runtime.Serialization; +using System.Security; + +namespace NHibernate.Util +{ + [Serializable] + internal sealed class SerializableMethodInfo : ISerializable, IEquatable + { + [NonSerialized] + private readonly MethodInfo _methodInfo; + + /// + /// Creates a new instance of if + /// is not null, otherwise returns null. + /// + /// The being wrapped for serialization. + /// New instance of or null. + public static SerializableMethodInfo Wrap(MethodInfo methodInfo) + { + return methodInfo == null ? null : new SerializableMethodInfo(methodInfo); + } + + /// + /// Creates a new + /// + /// The being wrapped for serialization. + private SerializableMethodInfo(MethodInfo methodInfo) + { + _methodInfo = methodInfo ?? throw new ArgumentNullException(nameof(methodInfo)); + if (methodInfo.IsStatic) throw new ArgumentException("Only for instance fields", nameof(methodInfo)); + if (methodInfo.DeclaringType == null) throw new ArgumentException("MethodInfo must have non-null DeclaringType", nameof(methodInfo)); + } + + private SerializableMethodInfo(SerializationInfo info, StreamingContext context) + { + System.Type declaringType = info.GetValue("declaringType").GetSystemType(); + string methodName = info.GetString("methodName"); + SerializableSystemType[] parameterSystemTypes = info.GetValue("parameterTypesHelper"); + + System.Type[] parameterTypes = parameterSystemTypes?.Select(x => x.GetSystemType()).ToArray() ?? new System.Type[0]; + _methodInfo = declaringType.GetMethod( + methodName, + BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null); + + if (_methodInfo == null) throw new MissingMethodException(declaringType.FullName, methodName); + } + + [SecurityCritical] + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + SerializableSystemType[] parameterSystemTypes = + _methodInfo.GetParameters() + .Select(x => SerializableSystemType.Wrap(x.ParameterType)) + .ToArray(); + + info.AddValue("declaringType", SerializableSystemType.Wrap(_methodInfo.DeclaringType)); + info.AddValue("methodName", _methodInfo.Name); + info.AddValue("parameterTypesHelper", parameterSystemTypes); + } + + public MethodInfo Value => _methodInfo; + + public bool Equals(SerializableMethodInfo other) + { + return other != null && Equals(_methodInfo, other._methodInfo); + } + } +} diff --git a/src/NHibernate/Util/SerializablePropertyInfo.cs b/src/NHibernate/Util/SerializablePropertyInfo.cs new file mode 100644 index 00000000000..0e902d8b6cf --- /dev/null +++ b/src/NHibernate/Util/SerializablePropertyInfo.cs @@ -0,0 +1,74 @@ +using System; +using System.Reflection; +using System.Runtime.Serialization; +using System.Security; + +namespace NHibernate.Util +{ + [Serializable] + internal sealed class SerializablePropertyInfo : ISerializable, IEquatable + { + [NonSerialized] + private readonly PropertyInfo _propertyInfo; + + /// + /// Creates a new instance of if + /// is not null, otherwise returns null. + /// + /// The being wrapped for serialization. + /// New instance of or null. + public static SerializablePropertyInfo Wrap(PropertyInfo propertyInfo) + { + return propertyInfo == null ? null : new SerializablePropertyInfo(propertyInfo); + } + + /// + /// Creates a new + /// + /// The being wrapped for serialization. + private SerializablePropertyInfo(PropertyInfo propertyInfo) + { + _propertyInfo = propertyInfo ?? throw new ArgumentNullException(nameof(propertyInfo)); + if (propertyInfo.DeclaringType == null) throw new ArgumentException("PropertyInfo must have non-null DeclaringType", nameof(propertyInfo)); + if (propertyInfo.GetIndexParameters().Length > 0) throw new ArgumentException("PropertyInfo not supported with IndexParameters", nameof(propertyInfo)); + } + + private SerializablePropertyInfo(SerializationInfo info, StreamingContext context) + { + System.Type declaringType = info.GetValue("declaringType").GetSystemType(); + string propertyName = info.GetString("propertyName"); + + _propertyInfo = declaringType.GetProperty( + propertyName, + BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + + if (_propertyInfo == null) throw new MissingMethodException(declaringType.FullName, propertyName); + } + + [SecurityCritical] + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("declaringType", SerializableSystemType.Wrap(_propertyInfo.DeclaringType)); + info.AddValue("propertyName", _propertyInfo.Name); + } + + public PropertyInfo Value => _propertyInfo; + + public bool Equals(SerializablePropertyInfo other) + { + return other != null && Equals(_propertyInfo, other._propertyInfo); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj is SerializablePropertyInfo && Equals((SerializablePropertyInfo) obj); + } + + public override int GetHashCode() + { + return (_propertyInfo != null ? _propertyInfo.GetHashCode() : 0); + } + } +} diff --git a/src/NHibernate/Util/SerializableSystemType.cs b/src/NHibernate/Util/SerializableSystemType.cs new file mode 100644 index 00000000000..2e1b6565db6 --- /dev/null +++ b/src/NHibernate/Util/SerializableSystemType.cs @@ -0,0 +1,145 @@ +using System; +using System.Runtime.Serialization; +using System.Security; + +namespace NHibernate.Util +{ + [Serializable] + internal class SerializableSystemType : ISerializable, IEquatable + { + [NonSerialized] + private readonly System.Type _type; + + private AssemblyQualifiedTypeName _typeName; + + protected AssemblyQualifiedTypeName TypeName => _typeName; + + /// + /// Creates a new instance of if + /// is not null, otherwise returns null. + /// + /// The being wrapped for serialization. + /// New instance of or null. + public static SerializableSystemType Wrap(System.Type type) + { + return type == null ? null : new SerializableSystemType(type); + } + + /// + /// Creates a new + /// + /// The being wrapped for serialization. + protected SerializableSystemType(System.Type type) + { + _type = type ?? throw new ArgumentNullException(nameof(type)); + } + + protected SerializableSystemType(SerializationInfo info, StreamingContext context) + { + _typeName = info.GetValue("_typeName"); + if (_typeName == null) + throw new InvalidOperationException("_typeName was null after deserialization"); + _type = _typeName.TypeFromAssembly(false); + } + + /// + /// Returns the wrapped type. Will throw if it was unable to load it after deserialization. + /// + /// The type that this class was initialized with or initialized after deserialization. + public System.Type GetSystemType() => _type ?? throw new TypeLoadException("Could not load type " + _typeName + "."); + + /// + /// Returns the wrapped type. Will return null if it was unable to load it after deserialization. + /// + /// The type that this class was initialized with, the type initialized after deserialization, or null if unable to load. + public System.Type TryGetSystemType() => _type; + + public string FullName => _type?.FullName ?? _typeName.Type; + + public string AssemblyQualifiedName => _type?.AssemblyQualifiedName ?? _typeName.ToString(); + + [SecurityCritical] + public virtual void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (_typeName == null) + { + _typeName = new AssemblyQualifiedTypeName(_type.FullName, _type.Assembly.FullName); + } + + info.AddValue("_typeName", _typeName); + } + + public bool Equals(SerializableSystemType other) + { + return other != null && + (_type == null || other._type == null + ? Equals(_typeName, other._typeName) + : Equals(_type, other._type)); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + return obj is SerializableSystemType type && Equals(type); + } + + public override int GetHashCode() + { + unchecked + { + return (FullName.GetHashCode() * 397) ^ (AssemblyQualifiedName?.GetHashCode() ?? 0); + } + } + } + + [Serializable] + internal sealed class ObjectReferenceSystemType : SerializableSystemType, IObjectReference + { + private readonly bool _throwOnDeserializationError; + + /// + /// Creates a new instance of if + /// is not null, otherwise returns null. + /// + /// The being wrapped for serialization. + /// for failing if unable to load the type + /// in , to yield + /// instead. + /// New instance of or null. + public static ObjectReferenceSystemType Wrap(System.Type type, bool throwOnDeserializationError) + { + return type == null ? null : new ObjectReferenceSystemType(type, throwOnDeserializationError); + } + + /// + /// Creates a new + /// + /// The being wrapped for serialization. + /// for failing if unable to load the type + /// in , to yield + /// instead. + private ObjectReferenceSystemType(System.Type type, bool throwOnDeserializationError) : base(type) + { + _throwOnDeserializationError = throwOnDeserializationError; + } + + private ObjectReferenceSystemType(SerializationInfo info, StreamingContext context) : base(info, context) + { + _throwOnDeserializationError = info.GetBoolean("_throwOnDeserializationError"); + } + + [SecurityCritical] + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + info.AddValue("_throwOnDeserializationError", _throwOnDeserializationError); + } + + [SecurityCritical] + object IObjectReference.GetRealObject(StreamingContext context) + { + return TypeName.TypeFromAssembly(_throwOnDeserializationError); + } + } +} diff --git a/src/NHibernate/Util/SerializationInfoExtensions.cs b/src/NHibernate/Util/SerializationInfoExtensions.cs new file mode 100644 index 00000000000..b6d2d68d931 --- /dev/null +++ b/src/NHibernate/Util/SerializationInfoExtensions.cs @@ -0,0 +1,14 @@ +using System; +using System.Runtime.Serialization; + +namespace NHibernate.Util +{ + internal static class SerializationInfoExtensions + { + public static T GetValue(this SerializationInfo info, string name) + { + if (info == null) throw new ArgumentNullException(nameof(info)); + return (T) info.GetValue(name, typeof(T)); + } + } +} From c0ac1e4c116d0083edc7d1172a871cf6c2ca9a71 Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Sat, 4 Nov 2017 10:29:25 -0700 Subject: [PATCH 4/4] Serialize system types in preparation for .NET Core. Serialize System.Type, ConstructorInfo, FieldInfo, MethodInfo, and PropertyInfo using only basic types. --- .../ExceptionsTest/SerializationFixture.cs | 24 ++++ src/NHibernate/Async/Impl/CriteriaImpl.cs | 1 + src/NHibernate/Async/Type/ArrayType.cs | 3 +- src/NHibernate/Async/Type/EntityType.cs | 35 +++-- src/NHibernate/Async/Type/SerializableType.cs | 3 +- src/NHibernate/Engine/Query/QueryPlanCache.cs | 24 +++- src/NHibernate/Impl/CriteriaImpl.cs | 17 ++- src/NHibernate/InstantiationException.cs | 29 ++-- .../Intercept/AbstractFieldInterceptor.cs | 18 ++- src/NHibernate/Mapping/Array.cs | 29 ++-- src/NHibernate/Mapping/Collection.cs | 20 +++ src/NHibernate/Mapping/Component.cs | 3 + src/NHibernate/Mapping/PersistentClass.cs | 45 +++--- src/NHibernate/Mapping/RootClass.cs | 16 ++- .../Properties/BasicPropertyAccessor.cs | 126 +++++++++-------- .../Properties/EmbeddedPropertyAccessor.cs | 70 ++++++---- src/NHibernate/Properties/FieldAccessor.cs | 131 ++++++++++-------- src/NHibernate/PropertyAccessException.cs | 44 +++--- .../DynamicProxy/ProxyObjectReference.cs | 3 + src/NHibernate/Proxy/LiteLazyInitializer.cs | 22 ++- .../Proxy/NHibernateProxyFactoryInfo.cs | 27 ++-- .../Proxy/Poco/BasicLazyInitializer.cs | 72 ++++++++-- ...AliasToBeanConstructorResultTransformer.cs | 35 +++-- .../Transform/AliasToBeanResultTransformer.cs | 71 +++++++--- .../Tuple/Component/PocoComponentTuplizer.cs | 64 +++++---- src/NHibernate/Tuple/PocoInstantiator.cs | 97 +++++++------ src/NHibernate/Type/AbstractEnumType.cs | 37 +++-- src/NHibernate/Type/ArrayType.cs | 41 ++++-- src/NHibernate/Type/EntityType.cs | 125 ++++++++--------- src/NHibernate/Type/SerializableType.cs | 48 ++++--- src/NHibernate/UnresolvableObjectException.cs | 52 +++---- 31 files changed, 806 insertions(+), 526 deletions(-) create mode 100644 src/NHibernate.Test/ExceptionsTest/SerializationFixture.cs diff --git a/src/NHibernate.Test/ExceptionsTest/SerializationFixture.cs b/src/NHibernate.Test/ExceptionsTest/SerializationFixture.cs new file mode 100644 index 00000000000..525e82b305a --- /dev/null +++ b/src/NHibernate.Test/ExceptionsTest/SerializationFixture.cs @@ -0,0 +1,24 @@ +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; +using NUnit.Framework; + +namespace NHibernate.Test.ExceptionsTest +{ + [TestFixture] + public class SerializationFixture + { + [Test] + public void InstantiationExceptionSerialization() + { + var formatter = new BinaryFormatter(); + using (var memoryStream = new MemoryStream()) + { + formatter.Serialize(memoryStream, new InstantiationException("test", GetType())); + memoryStream.Position = 0; + var ex = formatter.Deserialize(memoryStream) as InstantiationException; + Assert.That(ex, Is.Not.Null); + Assert.That(ex.PersistentType, Is.EqualTo(GetType())); + } + } + } +} diff --git a/src/NHibernate/Async/Impl/CriteriaImpl.cs b/src/NHibernate/Async/Impl/CriteriaImpl.cs index a40bc06bbd5..e73e21d327b 100644 --- a/src/NHibernate/Async/Impl/CriteriaImpl.cs +++ b/src/NHibernate/Async/Impl/CriteriaImpl.cs @@ -11,6 +11,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.Serialization; using System.Text; using System.Threading; using NHibernate.Criterion; diff --git a/src/NHibernate/Async/Type/ArrayType.cs b/src/NHibernate/Async/Type/ArrayType.cs index e3c4fcb9d2c..7114dcb58e8 100644 --- a/src/NHibernate/Async/Type/ArrayType.cs +++ b/src/NHibernate/Async/Type/ArrayType.cs @@ -12,6 +12,7 @@ using System.Collections; using System.Collections.Generic; using System.Data.Common; +using System.Runtime.Serialization; using NHibernate.Collection; using NHibernate.Engine; using NHibernate.Persister.Collection; @@ -70,4 +71,4 @@ public override async Task ReplaceElementsAsync(object original, object return result; } } -} \ No newline at end of file +} diff --git a/src/NHibernate/Async/Type/EntityType.cs b/src/NHibernate/Async/Type/EntityType.cs index 864d11c4dd2..0c3c2f639bd 100644 --- a/src/NHibernate/Async/Type/EntityType.cs +++ b/src/NHibernate/Async/Type/EntityType.cs @@ -18,6 +18,7 @@ using NHibernate.Proxy; using NHibernate.Util; using System.Collections.Generic; +using System.Runtime.Serialization; namespace NHibernate.Type { @@ -98,9 +99,9 @@ public override async Task ReplaceAsync(object original, object target, { return target; } - if (session.GetContextEntityIdentifier(original) == null && (await (ForeignKeys.IsTransientFastAsync(associatedEntityName, original, session, cancellationToken)).ConfigureAwait(false)).GetValueOrDefault()) + if (session.GetContextEntityIdentifier(original) == null && (await (ForeignKeys.IsTransientFastAsync(_associatedEntityName, original, session, cancellationToken)).ConfigureAwait(false)).GetValueOrDefault()) { - object copy = session.Factory.GetEntityPersister(associatedEntityName).Instantiate(null); + object copy = session.Factory.GetEntityPersister(_associatedEntityName).Instantiate(null); //TODO: should this be Session.instantiate(Persister, ...)? copyCache.Add(original, copy); return copy; @@ -129,7 +130,7 @@ public override async Task ReplaceAsync(object original, object target, /// /// An instance of the object or if the identifer was null. /// - public override sealed async Task NullSafeGetAsync(DbDataReader rs, string[] names, ISessionImplementor session, object owner, CancellationToken cancellationToken) + public sealed override async Task NullSafeGetAsync(DbDataReader rs, string[] names, ISessionImplementor session, object owner, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return await (ResolveIdentifierAsync(await (HydrateAsync(rs, names, session, owner, cancellationToken)).ConfigureAwait(false), session, owner, cancellationToken)).ConfigureAwait(false); @@ -144,10 +145,10 @@ protected async Task ResolveIdentifierAsync(object id, ISessionImplement { cancellationToken.ThrowIfCancellationRequested(); string entityName = GetAssociatedEntityName(); - bool isProxyUnwrapEnabled = unwrapProxy && session.Factory + bool isProxyUnwrapEnabled = _unwrapProxy && session.Factory .GetEntityPersister(entityName).IsInstrumented; - object proxyOrEntity = await (session.InternalLoadAsync(entityName, id, eager, IsNullable && !isProxyUnwrapEnabled, cancellationToken)).ConfigureAwait(false); + object proxyOrEntity = await (session.InternalLoadAsync(entityName, id, _eager, IsNullable && !isProxyUnwrapEnabled, cancellationToken)).ConfigureAwait(false); if (proxyOrEntity.IsProxy()) { @@ -178,21 +179,19 @@ public override Task ResolveIdentifierAsync(object value, ISessionImplem { return Task.FromResult(null); } - else + + if (IsNull(owner, session)) { - if (IsNull(owner, session)) - { - return Task.FromResult(null); //EARLY EXIT! - } + return Task.FromResult(null); //EARLY EXIT! + } - if (IsReferenceToPrimaryKey) - { - return ResolveIdentifierAsync(value, session, cancellationToken); - } - else - { - return LoadByUniqueKeyAsync(GetAssociatedEntityName(), _uniqueKeyPropertyName, value, session, cancellationToken); - } + if (IsReferenceToPrimaryKey) + { + return ResolveIdentifierAsync(value, session, cancellationToken); + } + else + { + return LoadByUniqueKeyAsync(GetAssociatedEntityName(), _uniqueKeyPropertyName, value, session, cancellationToken); } } catch (Exception ex) diff --git a/src/NHibernate/Async/Type/SerializableType.cs b/src/NHibernate/Async/Type/SerializableType.cs index 8acf9f5fc56..5ccbeb367e6 100644 --- a/src/NHibernate/Async/Type/SerializableType.cs +++ b/src/NHibernate/Async/Type/SerializableType.cs @@ -16,6 +16,7 @@ using System.Runtime.Serialization.Formatters.Binary; using NHibernate.Engine; using NHibernate.SqlTypes; +using NHibernate.Util; namespace NHibernate.Type { @@ -56,4 +57,4 @@ public override Task DisassembleAsync(object value, ISessionImplementor } } } -} \ No newline at end of file +} diff --git a/src/NHibernate/Engine/Query/QueryPlanCache.cs b/src/NHibernate/Engine/Query/QueryPlanCache.cs index 9b817c5eb87..2d501724bb8 100644 --- a/src/NHibernate/Engine/Query/QueryPlanCache.cs +++ b/src/NHibernate/Engine/Query/QueryPlanCache.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.Serialization; using NHibernate.Engine.Query.Sql; using NHibernate.Hql; using NHibernate.Linq; @@ -184,19 +185,16 @@ private class HQLQueryPlanKey : IEquatable private readonly bool shallow; private readonly HashSet filterNames; private readonly int hashCode; - private readonly System.Type queryTypeDiscriminator; - - public HQLQueryPlanKey(string query, bool shallow, IDictionary enabledFilters) - : this(typeof(object), query, shallow, enabledFilters) - { - } + [NonSerialized] + private System.Type queryTypeDiscriminator; + private SerializableSystemType _serializableQueryTypeDiscriminator; public HQLQueryPlanKey(IQueryExpression queryExpression, bool shallow, IDictionary enabledFilters) : this(queryExpression.GetType(), queryExpression.Key, shallow, enabledFilters) { } - protected HQLQueryPlanKey(System.Type queryTypeDiscriminator, string query, bool shallow, IDictionary enabledFilters) + private HQLQueryPlanKey(System.Type queryTypeDiscriminator, string query, bool shallow, IDictionary enabledFilters) { this.queryTypeDiscriminator = queryTypeDiscriminator; this.query = query; @@ -221,6 +219,18 @@ protected HQLQueryPlanKey(System.Type queryTypeDiscriminator, string query, bool } } + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableQueryTypeDiscriminator = SerializableSystemType.Wrap(queryTypeDiscriminator); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + queryTypeDiscriminator = _serializableQueryTypeDiscriminator?.GetSystemType(); + } + public override bool Equals(object obj) { return this == obj || Equals(obj as HQLQueryPlanKey); diff --git a/src/NHibernate/Impl/CriteriaImpl.cs b/src/NHibernate/Impl/CriteriaImpl.cs index 5e3bbb60d88..333c89ab553 100644 --- a/src/NHibernate/Impl/CriteriaImpl.cs +++ b/src/NHibernate/Impl/CriteriaImpl.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.Serialization; using System.Text; using System.Threading; using NHibernate.Criterion; @@ -17,7 +18,9 @@ namespace NHibernate.Impl [Serializable] public partial class CriteriaImpl : ICriteria { - private readonly System.Type persistentClass; + [NonSerialized] + private System.Type persistentClass; + private SerializableSystemType _serializablePersistentClass; private readonly List criteria = new List(); private readonly List orderEntries = new List(10); private readonly Dictionary fetchModes = new Dictionary(); @@ -72,6 +75,18 @@ public CriteriaImpl(string entityOrClassName, string alias, ISessionImplementor subcriteriaByAlias[alias] = this; } + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializablePersistentClass = SerializableSystemType.Wrap(persistentClass); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + persistentClass = _serializablePersistentClass?.GetSystemType(); + } + public ISessionImplementor Session { get { return session; } diff --git a/src/NHibernate/InstantiationException.cs b/src/NHibernate/InstantiationException.cs index 08496bffdc2..5b2c9cccdf2 100644 --- a/src/NHibernate/InstantiationException.cs +++ b/src/NHibernate/InstantiationException.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.Serialization; using System.Security; -using System.Security.Permissions; +using NHibernate.Util; namespace NHibernate { @@ -11,15 +11,13 @@ namespace NHibernate [Serializable] public class InstantiationException : HibernateException { - private readonly System.Type type; + [NonSerialized] + private readonly System.Type _type; public InstantiationException(string message, System.Type type) : base(message) { - if (type == null) - throw new ArgumentNullException("type"); - - this.type = type; + _type = type ?? throw new ArgumentNullException(nameof(type)); } /// @@ -35,19 +33,13 @@ public InstantiationException(string message, System.Type type) public InstantiationException(string message, Exception innerException, System.Type type) : base(message, innerException) { - if (type == null) - throw new ArgumentNullException("type"); - - this.type = type; + _type = type ?? throw new ArgumentNullException(nameof(type)); } /// /// Gets the that NHibernate was trying to instantiate. /// - public System.Type PersistentType - { - get { return type; } - } + public System.Type PersistentType => _type; /// /// Gets a message that describes the current . @@ -56,10 +48,7 @@ public System.Type PersistentType /// The error message that explains the reason for this exception and the Type that /// was trying to be instantiated. /// - public override string Message - { - get { return base.Message + (type == null ? "" : type.FullName); } - } + public override string Message => base.Message + (_type == null ? "" : _type.FullName); #region ISerializable Members @@ -76,7 +65,7 @@ public override string Message /// protected InstantiationException(SerializationInfo info, StreamingContext context) : base(info, context) { - this.type = info.GetValue("type", typeof(System.Type)) as System.Type; + _type = info.GetValue("type"); } /// @@ -94,7 +83,7 @@ protected InstantiationException(SerializationInfo info, StreamingContext contex public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); - info.AddValue("type", type, typeof(System.Type)); + info.AddValue("type", ObjectReferenceSystemType.Wrap(_type, true)); } #endregion diff --git a/src/NHibernate/Intercept/AbstractFieldInterceptor.cs b/src/NHibernate/Intercept/AbstractFieldInterceptor.cs index 1a170d921d3..76374076801 100644 --- a/src/NHibernate/Intercept/AbstractFieldInterceptor.cs +++ b/src/NHibernate/Intercept/AbstractFieldInterceptor.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Runtime.Serialization; using NHibernate.Engine; using NHibernate.Proxy; +using NHibernate.Util; namespace NHibernate.Intercept { @@ -16,7 +18,9 @@ public abstract class AbstractFieldInterceptor : IFieldInterceptor private readonly ISet unwrapProxyFieldNames; private readonly HashSet loadedUnwrapProxyFieldNames = new HashSet(); private readonly string entityName; - private readonly System.Type mappedClass; + [NonSerialized] + private System.Type mappedClass; + private SerializableSystemType _serializableMappedClass; [NonSerialized] private bool initializing; @@ -31,6 +35,18 @@ protected internal AbstractFieldInterceptor(ISessionImplementor session, ISet filters = new Dictionary(); private readonly Dictionary manyToManyFilters = new Dictionary(); private bool subselectLoadable; @@ -81,6 +87,20 @@ protected Collection(PersistentClass owner) this.owner = owner; } + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableCollectionPersisterClass = SerializableSystemType.Wrap(collectionPersisterClass); + _serializableGenericArguments = genericArguments?.Select(SerializableSystemType.Wrap).ToArray(); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + collectionPersisterClass = _serializableCollectionPersisterClass?.GetSystemType(); + genericArguments = _serializableGenericArguments?.Select(sst => sst?.GetSystemType()).ToArray(); + } + public int ColumnSpan { get { return 0; } diff --git a/src/NHibernate/Mapping/Component.cs b/src/NHibernate/Mapping/Component.cs index 33d5c3fee4d..2b6441b3772 100644 --- a/src/NHibernate/Mapping/Component.cs +++ b/src/NHibernate/Mapping/Component.cs @@ -14,7 +14,10 @@ namespace NHibernate.Mapping public class Component : SimpleValue, IMetaAttributable { private readonly List properties = new List(); + + [NonSerialized] private System.Type componentClass; + private bool embedded; private Property parentProperty; private PersistentClass owner; diff --git a/src/NHibernate/Mapping/PersistentClass.cs b/src/NHibernate/Mapping/PersistentClass.cs index b63a60a3e09..8ae13b2f8dc 100644 --- a/src/NHibernate/Mapping/PersistentClass.cs +++ b/src/NHibernate/Mapping/PersistentClass.cs @@ -63,7 +63,10 @@ public abstract class PersistentClass : IFilterable, IMetaAttributable, ISqlCust private Versioning.OptimisticLock optimisticLockMode; + [NonSerialized] private System.Type mappedClass; + + [NonSerialized] private System.Type proxyInterface; public string ClassName @@ -98,18 +101,17 @@ public virtual System.Type MappedClass { get { - if (mappedClass == null) + if (mappedClass != null) return mappedClass; + + if (className == null) + return null; + try { - if (className == null) - return null; - try - { - mappedClass = ReflectHelper.ClassForName(className); - } - catch (Exception cnfe) - { - throw new MappingException("entity class not found: " + className, cnfe); - } + mappedClass = ReflectHelper.ClassForName(className); + } + catch (Exception cnfe) + { + throw new MappingException("entity class not found: " + className, cnfe); } return mappedClass; } @@ -126,18 +128,17 @@ public virtual System.Type ProxyInterface { get { - if (proxyInterface == null) + if (proxyInterface != null) return proxyInterface; + + if (proxyInterfaceName == null) + return null; + try { - if (proxyInterfaceName == null) - return null; - try - { - proxyInterface = ReflectHelper.ClassForName(proxyInterfaceName); - } - catch (Exception cnfe) - { - throw new MappingException("proxy class not found: " + proxyInterfaceName, cnfe); - } + proxyInterface = ReflectHelper.ClassForName(proxyInterfaceName); + } + catch (Exception cnfe) + { + throw new MappingException("proxy class not found: " + proxyInterfaceName, cnfe); } return proxyInterface; } diff --git a/src/NHibernate/Mapping/RootClass.cs b/src/NHibernate/Mapping/RootClass.cs index 59210b16467..a2c66a34a24 100644 --- a/src/NHibernate/Mapping/RootClass.cs +++ b/src/NHibernate/Mapping/RootClass.cs @@ -1,7 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; - +using System.Runtime.Serialization; using NHibernate.Engine; using NHibernate.Util; @@ -40,13 +40,27 @@ public class RootClass : PersistentClass, ITableOwner private bool mutable; private bool embeddedIdentifier = false; private bool explicitPolymorphism; + [NonSerialized] private System.Type entityPersisterClass; + private SerializableSystemType _serializableEntityPersisterClass; private bool forceDiscriminator; private string where; private Table table; private bool discriminatorInsertable = true; private int nextSubclassId = 0; + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableEntityPersisterClass = SerializableSystemType.Wrap(entityPersisterClass); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + entityPersisterClass = _serializableEntityPersisterClass?.GetSystemType(); + } + public override int SubclassId { get { return 0; } diff --git a/src/NHibernate/Properties/BasicPropertyAccessor.cs b/src/NHibernate/Properties/BasicPropertyAccessor.cs index 18399171f31..e3f91ba0088 100644 --- a/src/NHibernate/Properties/BasicPropertyAccessor.cs +++ b/src/NHibernate/Properties/BasicPropertyAccessor.cs @@ -2,7 +2,9 @@ using System.Collections; using System.Reflection; using System.Reflection.Emit; +using System.Runtime.Serialization; using NHibernate.Engine; +using NHibernate.Util; namespace NHibernate.Properties { @@ -60,10 +62,7 @@ public ISetter GetSetter(System.Type type, string propertyName) return result; } - public bool CanAccessThroughReflectionOptimizer - { - get { return true; } - } + public bool CanAccessThroughReflectionOptimizer => true; #endregion @@ -161,9 +160,13 @@ internal static BasicSetter GetSetterOrNull(System.Type type, string propertyNam [Serializable] public sealed class BasicGetter : IGetter, IOptimizableGetter { - private readonly System.Type clazz; - private readonly PropertyInfo property; - private readonly string propertyName; + [NonSerialized] + private System.Type _clazz; + private SerializableSystemType _serializableClazz; + [NonSerialized] + private PropertyInfo _property; + private SerializablePropertyInfo _serializableProperty; + private readonly string _propertyName; /// /// Initializes a new instance of . @@ -173,16 +176,27 @@ public sealed class BasicGetter : IGetter, IOptimizableGetter /// The name of the Property. public BasicGetter(System.Type clazz, PropertyInfo property, string propertyName) { - this.clazz = clazz; - this.property = property; - this.propertyName = propertyName; + _clazz = clazz ?? throw new ArgumentNullException(nameof(clazz)); + _property = property ?? throw new ArgumentNullException(nameof(property)); + _propertyName = propertyName; + } + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableClazz = SerializableSystemType.Wrap(_clazz); + _serializableProperty = SerializablePropertyInfo.Wrap(_property); } - public PropertyInfo Property + [OnDeserialized] + private void OnDeserialized(StreamingContext context) { - get { return property; } + _clazz = _serializableClazz?.GetSystemType(); + _property = _serializableProperty?.Value; } + public PropertyInfo Property => _property; + #region IGetter Members /// @@ -196,11 +210,11 @@ public object Get(object target) { try { - return property.GetValue(target, Array.Empty()); + return _property.GetValue(target, Array.Empty()); } catch (Exception e) { - throw new PropertyAccessException(e, "Exception occurred", false, clazz, propertyName); + throw new PropertyAccessException(e, "Exception occurred", false, _clazz, _propertyName); } } @@ -208,19 +222,13 @@ public object Get(object target) /// Gets the that the Property returns. /// /// The that the Property returns. - public System.Type ReturnType - { - get { return property.PropertyType; } - } + public System.Type ReturnType => _property.PropertyType; /// /// Gets the name of the Property. /// /// The name of the Property. - public string PropertyName - { - get { return property.Name; } - } + public string PropertyName => _property.Name; /// /// Gets the for the Property. @@ -228,10 +236,7 @@ public string PropertyName /// /// The for the Property. /// - public MethodInfo Method - { - get { return property.GetGetMethod(true); } - } + public MethodInfo Method => _property.GetGetMethod(true); public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplementor session) { @@ -245,7 +250,7 @@ public void Emit(ILGenerator il) MethodInfo method = Method; if (method == null) { - throw new PropertyNotFoundException(clazz, property.Name, "getter"); + throw new PropertyNotFoundException(_clazz, _property.Name, "getter"); } il.EmitCall(OpCodes.Callvirt, method, null); } @@ -257,9 +262,13 @@ public void Emit(ILGenerator il) [Serializable] public sealed class BasicSetter : ISetter, IOptimizableSetter { - private readonly System.Type clazz; - private readonly PropertyInfo property; - private readonly string propertyName; + [NonSerialized] + private System.Type _clazz; + private SerializableSystemType _serializableClazz; + [NonSerialized] + private PropertyInfo _property; + private SerializablePropertyInfo _serializableProperty; + private readonly string _propertyName; /// /// Initializes a new instance of . @@ -269,16 +278,27 @@ public sealed class BasicSetter : ISetter, IOptimizableSetter /// The name of the mapped Property. public BasicSetter(System.Type clazz, PropertyInfo property, string propertyName) { - this.clazz = clazz; - this.property = property; - this.propertyName = propertyName; + _clazz = clazz ?? throw new ArgumentNullException(nameof(clazz)); + _property = property ?? throw new ArgumentNullException(nameof(property)); + _propertyName = propertyName; + } + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableClazz = SerializableSystemType.Wrap(_clazz); + _serializableProperty = SerializablePropertyInfo.Wrap(_property); } - public PropertyInfo Property + [OnDeserialized] + private void OnDeserialized(StreamingContext context) { - get { return property; } + _clazz = _serializableClazz?.GetSystemType(); + _property = _serializableProperty?.Value; } + public PropertyInfo Property => _property; + #region ISetter Members /// @@ -293,30 +313,31 @@ public void Set(object target, object value) { try { - property.SetValue(target, value, Array.Empty()); + _property.SetValue(target, value, Array.Empty()); } catch (ArgumentException ae) { // if I'm reading the msdn docs correctly this is the only reason the ArgumentException // would be thrown, but it doesn't hurt to make sure. - if (property.PropertyType.IsInstanceOfType(value) == false) + if (_property.PropertyType.IsInstanceOfType(value) == false) { // add some details to the error message - there have been a few forum posts an they are // all related to an ISet and IDictionary mixups. - string msg = - String.Format("The type {0} can not be assigned to a property of type {1}", value.GetType(), - property.PropertyType); - throw new PropertyAccessException(ae, msg, true, clazz, propertyName); + var msg = string.Format( + "The type {0} can not be assigned to a property of type {1}", value.GetType(), + _property.PropertyType); + throw new PropertyAccessException(ae, msg, true, _clazz, _propertyName); } else { - throw new PropertyAccessException(ae, "ArgumentException while setting the property value by reflection", true, - clazz, propertyName); + throw new PropertyAccessException( + ae, "ArgumentException while setting the property value by reflection", true, + _clazz, _propertyName); } } catch (Exception e) { - throw new PropertyAccessException(e, "could not set a property value by reflection", true, clazz, propertyName); + throw new PropertyAccessException(e, "could not set a property value by reflection", true, _clazz, _propertyName); } } @@ -324,24 +345,15 @@ public void Set(object target, object value) /// Gets the name of the mapped Property. /// /// The name of the mapped Property or . - public string PropertyName - { - get { return property.Name; } - } + public string PropertyName => _property.Name; /// /// Gets the for the mapped Property. /// /// The for the mapped Property. - public MethodInfo Method - { - get { return property.GetSetMethod(true); } - } + public MethodInfo Method => _property.GetSetMethod(true); - public System.Type Type - { - get { return property.PropertyType; } - } + public System.Type Type => _property.PropertyType; #endregion @@ -350,7 +362,7 @@ public void Emit(ILGenerator il) MethodInfo method = Method; if (method == null) { - throw new PropertyNotFoundException(clazz, property.Name, "setter"); + throw new PropertyNotFoundException(_clazz, _property.Name, "setter"); } il.EmitCall(OpCodes.Callvirt, method, null); } diff --git a/src/NHibernate/Properties/EmbeddedPropertyAccessor.cs b/src/NHibernate/Properties/EmbeddedPropertyAccessor.cs index 8e22d653bf4..a8a32dc7418 100644 --- a/src/NHibernate/Properties/EmbeddedPropertyAccessor.cs +++ b/src/NHibernate/Properties/EmbeddedPropertyAccessor.cs @@ -1,7 +1,9 @@ using System; using System.Collections; using System.Reflection; +using System.Runtime.Serialization; using NHibernate.Engine; +using NHibernate.Util; namespace NHibernate.Properties { @@ -20,45 +22,47 @@ public ISetter GetSetter(System.Type theClass, string propertyName) return new EmbeddedSetter(theClass); } - public bool CanAccessThroughReflectionOptimizer - { - get { return false; } - } + public bool CanAccessThroughReflectionOptimizer => false; #endregion [Serializable] public sealed class EmbeddedGetter : IGetter { - private readonly System.Type clazz; + [NonSerialized] + private System.Type _clazz; + private SerializableSystemType _serializableClazz; internal EmbeddedGetter(System.Type clazz) { - this.clazz = clazz; + _clazz = clazz ?? throw new ArgumentNullException(nameof(clazz)); } - #region IGetter Members - - public object Get(object target) + [OnSerializing] + private void OnSerializing(StreamingContext context) { - return target; + _serializableClazz = SerializableSystemType.Wrap(_clazz); } - public System.Type ReturnType + [OnDeserialized] + private void OnDeserialized(StreamingContext context) { - get { return clazz; } + _clazz = _serializableClazz?.GetSystemType(); } - public string PropertyName - { - get { return null; } - } + #region IGetter Members - public MethodInfo Method + public object Get(object target) { - get { return null; } + return target; } + public System.Type ReturnType => _clazz; + + public string PropertyName => null; + + public MethodInfo Method => null; + public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplementor session) { return Get(owner); @@ -68,41 +72,49 @@ public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplement public override string ToString() { - return string.Format("EmbeddedGetter({0})", clazz.FullName); + return string.Format("EmbeddedGetter({0})", _clazz.FullName); } } [Serializable] public sealed class EmbeddedSetter : ISetter { - private readonly System.Type clazz; + [NonSerialized] + private System.Type _clazz; + private SerializableSystemType _serializableClazz; internal EmbeddedSetter(System.Type clazz) { - this.clazz = clazz; + _clazz = clazz ?? throw new ArgumentNullException(nameof(clazz)); } - #region ISetter Members - - public void Set(object target, object value) + [OnSerializing] + private void OnSerializing(StreamingContext context) { + _serializableClazz = SerializableSystemType.Wrap(_clazz); } - public string PropertyName + [OnDeserialized] + private void OnDeserialized(StreamingContext context) { - get { return null; } + _clazz = _serializableClazz?.GetSystemType(); } - public MethodInfo Method + #region ISetter Members + + public void Set(object target, object value) { - get { return null; } } + public string PropertyName => null; + + public MethodInfo Method => null; + #endregion public override string ToString() { - return string.Format("EmbeddedSetter({0})", clazz.FullName); + return string.Format("EmbeddedSetter({0})", _clazz.FullName); } } diff --git a/src/NHibernate/Properties/FieldAccessor.cs b/src/NHibernate/Properties/FieldAccessor.cs index 5a4b4df3854..48b1b3dd7ec 100644 --- a/src/NHibernate/Properties/FieldAccessor.cs +++ b/src/NHibernate/Properties/FieldAccessor.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Reflection; using System.Reflection.Emit; +using System.Runtime.Serialization; using NHibernate.Engine; using NHibernate.Util; @@ -18,7 +19,7 @@ namespace NHibernate.Properties [Serializable] public class FieldAccessor : IPropertyAccessor { - private readonly IFieldNamingStrategy namingStrategy; + private readonly IFieldNamingStrategy _namingStrategy; /// /// Initializes a new instance of . @@ -33,7 +34,7 @@ public FieldAccessor() /// The to use. public FieldAccessor(IFieldNamingStrategy namingStrategy) { - this.namingStrategy = namingStrategy; + _namingStrategy = namingStrategy; } /// @@ -41,10 +42,7 @@ public FieldAccessor(IFieldNamingStrategy namingStrategy) /// mapped Property in the hbm.xml file to the name of the field in the class. /// /// The or . - public IFieldNamingStrategy NamingStrategy - { - get { return namingStrategy; } - } + public IFieldNamingStrategy NamingStrategy => _namingStrategy; #region IPropertyAccessor Members @@ -92,10 +90,7 @@ public ISetter GetSetter(System.Type theClass, string propertyName) return new FieldSetter(GetField(theClass, fieldName), theClass, fieldName); } - public bool CanAccessThroughReflectionOptimizer - { - get { return true; } - } + public bool CanAccessThroughReflectionOptimizer => true; #endregion @@ -144,13 +139,13 @@ internal static FieldInfo GetField(System.Type type, string fieldName) /// The name of the Field. private string GetFieldName(string propertyName) { - if (namingStrategy == null) + if (_namingStrategy == null) { return propertyName; } else { - return namingStrategy.GetFieldName(propertyName); + return _namingStrategy.GetFieldName(propertyName); } } @@ -160,9 +155,11 @@ private string GetFieldName(string propertyName) [Serializable] public sealed class FieldGetter : IGetter, IOptimizableGetter { - private readonly FieldInfo field; - private readonly System.Type clazz; - private readonly string name; + private FieldInfo _field; + private SerializableFieldInfo _serializableField; + private System.Type _clazz; + private SerializableSystemType _serializableClazz; + private readonly string _name; /// /// Initializes a new instance of . @@ -172,9 +169,23 @@ public sealed class FieldGetter : IGetter, IOptimizableGetter /// The name of the Field. public FieldGetter(FieldInfo field, System.Type clazz, string name) { - this.field = field; - this.clazz = clazz; - this.name = name; + _field = field ?? throw new ArgumentNullException(nameof(field)); + _clazz = clazz ?? throw new ArgumentNullException(nameof(clazz)); + _name = name; + } + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableClazz = SerializableSystemType.Wrap(_clazz); + _serializableField = SerializableFieldInfo.Wrap(_field); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + _clazz = _serializableClazz?.GetSystemType(); + _field = _serializableField?.Value; } #region IGetter Members @@ -190,11 +201,11 @@ public object Get(object target) { try { - return field.GetValue(target); + return _field.GetValue(target); } catch (Exception e) { - throw new PropertyAccessException(e, "could not get a field value by reflection", false, clazz, name); + throw new PropertyAccessException(e, "could not get a field value by reflection", false, _clazz, _name); } } @@ -202,28 +213,19 @@ public object Get(object target) /// Gets the that the Field returns. /// /// The that the Field returns. - public System.Type ReturnType - { - get { return field.FieldType; } - } + public System.Type ReturnType => _field.FieldType; /// /// Gets the name of the Property. /// /// since this is a Field - not a Property. - public string PropertyName - { - get { return null; } - } + public string PropertyName => null; /// /// Gets the for the Property. /// /// since this is a Field - not a Property. - public MethodInfo Method - { - get { return null; } - } + public MethodInfo Method => null; public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplementor session) { @@ -234,7 +236,7 @@ public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplement public void Emit(ILGenerator il) { - il.Emit(OpCodes.Ldfld, field); + il.Emit(OpCodes.Ldfld, _field); } } @@ -244,9 +246,11 @@ public void Emit(ILGenerator il) [Serializable] public sealed class FieldSetter : ISetter, IOptimizableSetter { - private readonly FieldInfo field; - private readonly System.Type clazz; - private readonly string name; + private FieldInfo _field; + private SerializableFieldInfo _serializableField; + private System.Type _clazz; + private SerializableSystemType _serializableClazz; + private readonly string _name; /// /// Initializes a new instance of . @@ -256,9 +260,23 @@ public sealed class FieldSetter : ISetter, IOptimizableSetter /// The name of the Field. public FieldSetter(FieldInfo field, System.Type clazz, string name) { - this.field = field; - this.clazz = clazz; - this.name = name; + _field = field ?? throw new ArgumentNullException(nameof(field)); + _clazz = clazz ?? throw new ArgumentNullException(nameof(clazz)); + _name = name; + } + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableClazz = SerializableSystemType.Wrap(_clazz); + _serializableField = SerializableFieldInfo.Wrap(_field); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + _clazz = _serializableClazz?.GetSystemType(); + _field = _serializableField?.Value; } #region ISetter Members @@ -275,30 +293,30 @@ public void Set(object target, object value) { try { - field.SetValue(target, value); + _field.SetValue(target, value); } catch (ArgumentException ae) { // if I'm reading the msdn docs correctly this is the only reason the ArgumentException // would be thrown, but it doesn't hurt to make sure. - if (field.FieldType.IsInstanceOfType(value) == false) + if (_field.FieldType.IsInstanceOfType(value) == false) { // add some details to the error message - there have been a few forum posts an they are // all related to an ISet and IDictionary mixups. - string msg = - String.Format("The type {0} can not be assigned to a field of type {1}", value.GetType().ToString(), - field.FieldType.ToString()); - throw new PropertyAccessException(ae, msg, true, clazz, name); + var msg = string.Format( + "The type {0} can not be assigned to a field of type {1}", value.GetType(), + _field.FieldType); + throw new PropertyAccessException(ae, msg, true, _clazz, _name); } else { - throw new PropertyAccessException(ae, "ArgumentException while setting the field value by reflection", true, clazz, - name); + throw new PropertyAccessException( + ae, "ArgumentException while setting the field value by reflection", true, _clazz, _name); } } catch (Exception e) { - throw new PropertyAccessException(e, "could not set a field value by reflection", true, clazz, name); + throw new PropertyAccessException(e, "could not set a field value by reflection", true, _clazz, _name); } } @@ -306,30 +324,21 @@ public void Set(object target, object value) /// Gets the name of the Property. /// /// since this is a Field - not a Property. - public string PropertyName - { - get { return null; } - } + public string PropertyName => null; /// /// Gets the for the Property. /// /// since this is a Field - not a Property. - public MethodInfo Method - { - get { return null; } - } + public MethodInfo Method => null; - public System.Type Type - { - get { return field.FieldType; } - } + public System.Type Type => _field.FieldType; #endregion public void Emit(ILGenerator il) { - il.Emit(OpCodes.Stfld, field); + il.Emit(OpCodes.Stfld, _field); } } } diff --git a/src/NHibernate/PropertyAccessException.cs b/src/NHibernate/PropertyAccessException.cs index 47666cd249a..f33020fbc30 100644 --- a/src/NHibernate/PropertyAccessException.cs +++ b/src/NHibernate/PropertyAccessException.cs @@ -1,7 +1,7 @@ using System; using System.Runtime.Serialization; using System.Security; -using System.Security.Permissions; +using NHibernate.Util; namespace NHibernate { @@ -11,9 +11,10 @@ namespace NHibernate [Serializable] public class PropertyAccessException : HibernateException, ISerializable { - private readonly System.Type persistentType; - private readonly string propertyName; - private readonly bool wasSetter; + [NonSerialized] + private readonly System.Type _persistentType; + private readonly string _propertyName; + private readonly bool _wasSetter; /// /// Initializes a new instance of the class. @@ -31,25 +32,22 @@ public PropertyAccessException(Exception innerException, string message, bool wa string propertyName) : base(message, innerException) { - this.persistentType = persistentType; - this.wasSetter = wasSetter; - this.propertyName = propertyName; + _persistentType = persistentType; + _wasSetter = wasSetter; + _propertyName = propertyName; } public PropertyAccessException(Exception innerException, string message, bool wasSetter, System.Type persistentType) : base(message, innerException) { - this.persistentType = persistentType; - this.wasSetter = wasSetter; + _persistentType = persistentType; + _wasSetter = wasSetter; } /// /// Gets the that NHibernate was trying find the Property or Field in. /// - public System.Type PersistentType - { - get { return persistentType; } - } + public System.Type PersistentType => _persistentType; /// /// Gets a message that describes the current . @@ -62,9 +60,9 @@ public override string Message { get { - return base.Message + (wasSetter ? " setter of " : " getter of ") + - (persistentType == null ? "UnknownType" : persistentType.FullName) + - (string.IsNullOrEmpty(propertyName) ? string.Empty: "." + propertyName); + return base.Message + (_wasSetter ? " setter of " : " getter of ") + + (_persistentType == null ? "UnknownType" : _persistentType.FullName) + + (string.IsNullOrEmpty(_propertyName) ? string.Empty: "." + _propertyName); } } @@ -83,9 +81,9 @@ public override string Message /// protected PropertyAccessException(SerializationInfo info, StreamingContext context) : base(info, context) { - persistentType = info.GetValue("persistentType", typeof(System.Type)) as System.Type; - propertyName = info.GetString("propertyName"); - wasSetter = info.GetBoolean("wasSetter"); + _propertyName = info.GetString("propertyName"); + _wasSetter = info.GetBoolean("wasSetter"); + _persistentType = info.GetValue("persistentType"); } /// @@ -103,11 +101,11 @@ protected PropertyAccessException(SerializationInfo info, StreamingContext conte public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); - info.AddValue("persistentType", persistentType, typeof(System.Type)); - info.AddValue("propertyName", propertyName); - info.AddValue("wasSetter", wasSetter); + info.AddValue("persistentType", ObjectReferenceSystemType.Wrap(_persistentType, true)); + info.AddValue("propertyName", _propertyName); + info.AddValue("wasSetter", _wasSetter); } #endregion } -} \ No newline at end of file +} diff --git a/src/NHibernate/Proxy/DynamicProxy/ProxyObjectReference.cs b/src/NHibernate/Proxy/DynamicProxy/ProxyObjectReference.cs index 4b6f99d2f30..f0a5ac44ff3 100644 --- a/src/NHibernate/Proxy/DynamicProxy/ProxyObjectReference.cs +++ b/src/NHibernate/Proxy/DynamicProxy/ProxyObjectReference.cs @@ -16,7 +16,10 @@ namespace NHibernate.Proxy.DynamicProxy [Serializable] public class ProxyObjectReference : IObjectReference, ISerializable { + [NonSerialized] private readonly System.Type _baseType; + + [NonSerialized] private readonly IProxy _proxy; protected ProxyObjectReference(SerializationInfo info, StreamingContext context) diff --git a/src/NHibernate/Proxy/LiteLazyInitializer.cs b/src/NHibernate/Proxy/LiteLazyInitializer.cs index 9684bbed5f7..0272523e3e4 100644 --- a/src/NHibernate/Proxy/LiteLazyInitializer.cs +++ b/src/NHibernate/Proxy/LiteLazyInitializer.cs @@ -1,17 +1,35 @@ using System; +using System.Runtime.Serialization; using NHibernate.Engine; +using NHibernate.Util; namespace NHibernate.Proxy { [Serializable] internal sealed class LiteLazyInitializer : AbstractLazyInitializer { + [NonSerialized] + private System.Type _persistentClass; + private SerializableSystemType _serializablePersistentClass; + internal LiteLazyInitializer(string entityName, object id, ISessionImplementor session, System.Type persistentClass) : base(entityName, id, session) { - PersistentClass = persistentClass; + _persistentClass = persistentClass; } - public override System.Type PersistentClass { get; } + public override System.Type PersistentClass => _persistentClass; + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializablePersistentClass = SerializableSystemType.Wrap(_persistentClass); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + _persistentClass = _serializablePersistentClass?.GetSystemType(); + } } } diff --git a/src/NHibernate/Proxy/NHibernateProxyFactoryInfo.cs b/src/NHibernate/Proxy/NHibernateProxyFactoryInfo.cs index 065c3705729..3d4f6800923 100644 --- a/src/NHibernate/Proxy/NHibernateProxyFactoryInfo.cs +++ b/src/NHibernate/Proxy/NHibernateProxyFactoryInfo.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Runtime.Serialization; using System.Security; using NHibernate.Type; +using NHibernate.Util; namespace NHibernate.Proxy { @@ -11,10 +13,19 @@ namespace NHibernate.Proxy public sealed class NHibernateProxyFactoryInfo : ISerializable { private readonly string _entityName; + + [NonSerialized] private readonly System.Type _persistentClass; + + [NonSerialized] private readonly System.Type[] _interfaces; + + [NonSerialized] private readonly MethodInfo _getIdentifierMethod; + + [NonSerialized] private readonly MethodInfo _setIdentifierMethod; + private readonly IAbstractComponentType _componentIdType; internal NHibernateProxyFactoryInfo(string entityName, System.Type persistentClass, System.Type[] interfaces, MethodInfo getIdentifierMethod, MethodInfo setIdentifierMethod, IAbstractComponentType componentIdType) @@ -37,10 +48,10 @@ public IProxyFactory CreateProxyFactory() private NHibernateProxyFactoryInfo(SerializationInfo info, StreamingContext context) { _entityName = (string) info.GetValue(nameof(_entityName), typeof(string)); - _persistentClass = (System.Type) info.GetValue(nameof(_persistentClass), typeof(System.Type)); - _interfaces = (System.Type[]) info.GetValue(nameof(_interfaces), typeof(System.Type[])); - _getIdentifierMethod = (MethodInfo) info.GetValue(nameof(_getIdentifierMethod), typeof(MethodInfo)); - _setIdentifierMethod = (MethodInfo) info.GetValue(nameof(_setIdentifierMethod), typeof(MethodInfo)); + _persistentClass = info.GetValue(nameof(_persistentClass))?.GetSystemType(); + _interfaces = info.GetValue(nameof(_interfaces))?.Select(x => x?.GetSystemType()).ToArray(); + _getIdentifierMethod = info.GetValue(nameof(_getIdentifierMethod))?.Value; + _setIdentifierMethod = info.GetValue(nameof(_setIdentifierMethod))?.Value; _componentIdType = (IAbstractComponentType) info.GetValue(nameof(_componentIdType), typeof(IAbstractComponentType)); } @@ -48,10 +59,10 @@ private NHibernateProxyFactoryInfo(SerializationInfo info, StreamingContext cont public void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue(nameof(_entityName), _entityName); - info.AddValue(nameof(_persistentClass), _persistentClass); - info.AddValue(nameof(_interfaces), _interfaces); - info.AddValue(nameof(_getIdentifierMethod), _getIdentifierMethod); - info.AddValue(nameof(_setIdentifierMethod), _setIdentifierMethod); + info.AddValue(nameof(_persistentClass), SerializableSystemType.Wrap(_persistentClass)); + info.AddValue(nameof(_interfaces), _interfaces?.Select(SerializableSystemType.Wrap).ToArray()); + info.AddValue(nameof(_getIdentifierMethod), SerializableMethodInfo.Wrap(_getIdentifierMethod)); + info.AddValue(nameof(_setIdentifierMethod), SerializableMethodInfo.Wrap(_setIdentifierMethod)); info.AddValue(nameof(_componentIdType), _componentIdType); } } diff --git a/src/NHibernate/Proxy/Poco/BasicLazyInitializer.cs b/src/NHibernate/Proxy/Poco/BasicLazyInitializer.cs index 8c7aed84af4..1fe3e81c786 100644 --- a/src/NHibernate/Proxy/Poco/BasicLazyInitializer.cs +++ b/src/NHibernate/Proxy/Poco/BasicLazyInitializer.cs @@ -14,22 +14,75 @@ public abstract class BasicLazyInitializer : AbstractLazyInitializer { private static readonly IEqualityComparer IdentityEqualityComparer = new IdentityEqualityComparer(); - internal System.Type persistentClass; + // Since 5.1 + [Obsolete("This field has no inherited usages in NHibernate and will be removed.")] + [NonSerialized] protected internal MethodInfo getIdentifierMethod; + // Since 5.1 + [Obsolete("This field has no inherited usages in NHibernate and will be removed.")] + [NonSerialized] protected internal MethodInfo setIdentifierMethod; + // Since 5.1 + [Obsolete("This field has no inherited usages in NHibernate and will be removed.")] + [NonSerialized] protected internal bool overridesEquals; + // Since 5.1 + [Obsolete("This field has no inherited usages in NHibernate and will be removed.")] + [NonSerialized] protected internal IAbstractComponentType componentIdType; + [NonSerialized] + private System.Type _persistentClass; + private SerializableSystemType _serializablePersistentClass; + [NonSerialized] + private MethodInfo _getIdentifierMethod; + private SerializableMethodInfo _serializableGetIdentifierMethod; + [NonSerialized] + private MethodInfo _setIdentifierMethod; + private SerializableMethodInfo _serializableSetIdentifierMethod; + private readonly bool _overridesEquals; + private readonly IAbstractComponentType _componentIdType; + protected internal BasicLazyInitializer(string entityName, System.Type persistentClass, object id, MethodInfo getIdentifierMethod, MethodInfo setIdentifierMethod, IAbstractComponentType componentIdType, ISessionImplementor session, bool overridesEquals) : base(entityName, id, session) { - this.persistentClass = persistentClass; + _persistentClass = persistentClass; + _getIdentifierMethod = getIdentifierMethod; + _setIdentifierMethod = setIdentifierMethod; + _componentIdType = componentIdType; + _overridesEquals = overridesEquals; + +#pragma warning disable 618 this.getIdentifierMethod = getIdentifierMethod; this.setIdentifierMethod = setIdentifierMethod; this.componentIdType = componentIdType; this.overridesEquals = overridesEquals; +#pragma warning restore 618 + } + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializablePersistentClass = SerializableSystemType.Wrap(_persistentClass); + _serializableGetIdentifierMethod = SerializableMethodInfo.Wrap(_getIdentifierMethod); + _serializableSetIdentifierMethod = SerializableMethodInfo.Wrap(_setIdentifierMethod); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + _persistentClass = _serializablePersistentClass?.GetSystemType(); + _getIdentifierMethod = _serializableGetIdentifierMethod?.Value; + _setIdentifierMethod = _serializableSetIdentifierMethod?.Value; + +#pragma warning disable 618 + getIdentifierMethod = _getIdentifierMethod; + setIdentifierMethod = _setIdentifierMethod; + componentIdType = _componentIdType; + overridesEquals = _overridesEquals; +#pragma warning restore 618 } /// @@ -47,7 +100,7 @@ protected virtual void AddSerializationInfo(SerializationInfo info, StreamingCon public override System.Type PersistentClass { - get { return persistentClass; } + get { return _persistentClass; } } /// @@ -69,7 +122,7 @@ public virtual object Invoke(MethodInfo method, object[] args, object proxy) if (paramCount == 0) { - if (!overridesEquals && methodName == "GetHashCode") + if (!_overridesEquals && methodName == "GetHashCode") { return IdentityEqualityComparer.GetHashCode(proxy); } @@ -88,11 +141,11 @@ public virtual object Invoke(MethodInfo method, object[] args, object proxy) } else if (paramCount == 1) { - if (!overridesEquals && methodName == "Equals") + if (!_overridesEquals && methodName == "Equals") { return IdentityEqualityComparer.Equals(args[0], proxy); } - else if (setIdentifierMethod!=null&&method.Equals(setIdentifierMethod)) + else if (_setIdentifierMethod != null && method.Equals(_setIdentifierMethod)) { Initialize(); Identifier = args[0]; @@ -127,7 +180,7 @@ public virtual object Invoke(MethodInfo method, object[] args, object proxy) } //if it is a property of an embedded component, invoke on the "identifier" - if (componentIdType != null && componentIdType.IsMethodOf(method)) + if (_componentIdType != null && _componentIdType.IsMethodOf(method)) { return method.Invoke(Identifier, args); } @@ -137,13 +190,14 @@ public virtual object Invoke(MethodInfo method, object[] args, object proxy) private bool IsEqualToIdentifierMethod(MethodInfo method) { - if (getIdentifierMethod != null) + if (_getIdentifierMethod != null) { // in the case of inherited identifier methods (from a base class or an iterface) the // passed in MethodBase object is not equal to the getIdentifierMethod instance that we // have... but if their names and return types are identical, then it is the correct // identifier method - return method.Name.Equals(getIdentifierMethod.Name) && method.ReturnType.Equals(getIdentifierMethod.ReturnType); + return method.Name.Equals(_getIdentifierMethod.Name) + && method.ReturnType.Equals(_getIdentifierMethod.ReturnType); } return false; diff --git a/src/NHibernate/Transform/AliasToBeanConstructorResultTransformer.cs b/src/NHibernate/Transform/AliasToBeanConstructorResultTransformer.cs index 7be85aa8fba..b905eaf9077 100644 --- a/src/NHibernate/Transform/AliasToBeanConstructorResultTransformer.cs +++ b/src/NHibernate/Transform/AliasToBeanConstructorResultTransformer.cs @@ -1,34 +1,45 @@ using System; using System.Collections; using System.Reflection; +using System.Runtime.Serialization; +using NHibernate.Util; namespace NHibernate.Transform { [Serializable] public class AliasToBeanConstructorResultTransformer : IResultTransformer { - private readonly ConstructorInfo constructor; + [NonSerialized] + private ConstructorInfo _constructor; + private SerializableConstructorInfo _serializableConstructor; public AliasToBeanConstructorResultTransformer(ConstructorInfo constructor) { - if (constructor == null) - { - throw new ArgumentNullException("constructor"); - } - this.constructor = constructor; + _constructor = constructor ?? throw new ArgumentNullException(nameof(constructor)); + } + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableConstructor = SerializableConstructorInfo.Wrap(_constructor); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + _constructor = _serializableConstructor?.Value; } public object TransformTuple(object[] tuple, string[] aliases) { try { - return constructor.Invoke(tuple); + return _constructor.Invoke(tuple); } catch (Exception e) { throw new QueryException( - "could not instantiate: " + - constructor.DeclaringType.FullName, + $"could not instantiate: {_constructor.DeclaringType.FullName}", e); } } @@ -48,7 +59,7 @@ public bool Equals(AliasToBeanConstructorResultTransformer other) { return true; } - return Equals(other.constructor, constructor); + return Equals(other._constructor, _constructor); } public override bool Equals(object obj) @@ -58,7 +69,7 @@ public override bool Equals(object obj) public override int GetHashCode() { - return constructor.GetHashCode(); + return _constructor.GetHashCode(); } } -} \ No newline at end of file +} diff --git a/src/NHibernate/Transform/AliasToBeanResultTransformer.cs b/src/NHibernate/Transform/AliasToBeanResultTransformer.cs index 96a0677f256..414a066512f 100644 --- a/src/NHibernate/Transform/AliasToBeanResultTransformer.cs +++ b/src/NHibernate/Transform/AliasToBeanResultTransformer.cs @@ -1,8 +1,11 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Data.SqlTypes; using System.Linq; using System.Reflection; +using System.Runtime.Serialization; +using NHibernate.Util; namespace NHibernate.Transform { @@ -33,32 +36,56 @@ namespace NHibernate.Transform [Serializable] public class AliasToBeanResultTransformer : AliasedTupleSubsetResultTransformer, IEquatable { - private readonly System.Type _resultClass; - private readonly ConstructorInfo _beanConstructor; - private readonly Dictionary> _fieldsByNameCaseSensitive; - private readonly Dictionary> _fieldsByNameCaseInsensitive; - private readonly Dictionary> _propertiesByNameCaseSensitive; - private readonly Dictionary> _propertiesByNameCaseInsensitive; + [NonSerialized] + private System.Type _resultClass; + private SerializableSystemType _serializableResultClass; + [NonSerialized] + private ConstructorInfo _beanConstructor; + [NonSerialized] + private Dictionary> _fieldsByNameCaseSensitive; + [NonSerialized] + private Dictionary> _fieldsByNameCaseInsensitive; + [NonSerialized] + private Dictionary> _propertiesByNameCaseSensitive; + [NonSerialized] + private Dictionary> _propertiesByNameCaseInsensitive; public AliasToBeanResultTransformer(System.Type resultClass) { - _resultClass = resultClass ?? throw new ArgumentNullException("resultClass"); + _resultClass = resultClass ?? throw new ArgumentNullException(nameof(resultClass)); + InitializeTransformer(); + } + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableResultClass = SerializableSystemType.Wrap(_resultClass); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + _resultClass = _serializableResultClass?.GetSystemType(); + InitializeTransformer(); + } + + private void InitializeTransformer() + { const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; - _beanConstructor = resultClass.GetConstructor(bindingFlags, null, System.Type.EmptyTypes, null); + _beanConstructor = _resultClass.GetConstructor(bindingFlags, null, System.Type.EmptyTypes, null); // if resultClass is a ValueType (struct), GetConstructor will return null... // in that case, we'll use Activator.CreateInstance instead of the ConstructorInfo to create instances - if (_beanConstructor == null && resultClass.IsClass) + if (_beanConstructor == null && _resultClass.IsClass) { - throw new ArgumentException( - "The target class of a AliasToBeanResultTransformer need a parameter-less constructor", - nameof(resultClass)); + throw new InvalidOperationException( + "The target class of a AliasToBeanResultTransformer need a parameter-less constructor"); } var fields = new List>(); var properties = new List>(); - FetchFieldsAndProperties(fields, properties); + FetchFieldsAndProperties(_resultClass, fields, properties); _fieldsByNameCaseSensitive = GetMapByName(fields, StringComparer.Ordinal); _fieldsByNameCaseInsensitive = GetMapByName(fields, StringComparer.OrdinalIgnoreCase); @@ -75,7 +102,7 @@ public override object TransformTuple(object[] tuple, String[] aliases) { if (aliases == null) { - throw new ArgumentNullException("aliases"); + throw new ArgumentNullException(nameof(aliases)); } object result; @@ -137,7 +164,7 @@ private void SetProperty(string alias, object value, object resultObj) throw new PropertyNotFoundException(resultObj.GetType(), alias, "setter"); } - private bool TrySet(string alias, object value, object resultObj, Dictionary> fieldsMap) + private static bool TrySet(string alias, object value, object resultObj, Dictionary> fieldsMap) { if (fieldsMap.TryGetValue(alias, out var field)) { @@ -148,7 +175,7 @@ private bool TrySet(string alias, object value, object resultObj, Dictionary> propertiesMap) + private static bool TrySet(string alias, object value, object resultObj, Dictionary> propertiesMap) { if (propertiesMap.TryGetValue(alias, out var property)) { @@ -159,7 +186,7 @@ private bool TrySet(string alias, object value, object resultObj, Dictionary(NamedMember member, string alias) where T : MemberInfo + private static void CheckMember(NamedMember member, string alias) where T : MemberInfo { if (member.Member != null) return; @@ -177,10 +204,9 @@ private void CheckMember(NamedMember member, string alias) where T : Membe $"{string.Join(", ", member.AmbiguousMembers.Select(m => m.Name))}"); } - private void FetchFieldsAndProperties(List> fields, List> properties) + private static void FetchFieldsAndProperties(System.Type currentType, List> fields, List> properties) { const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly; - var currentType = _resultClass; var rank = 1; // For grasping private members, we need to manually walk the hierarchy. while (currentType != null && currentType != typeof(object)) @@ -199,7 +225,7 @@ private void FetchFieldsAndProperties(List> fields, List } } - private int GetFieldVisibilityRank(FieldInfo field) + private static int GetFieldVisibilityRank(FieldInfo field) { if (field.IsPublic) return 1; @@ -212,7 +238,7 @@ private int GetFieldVisibilityRank(FieldInfo field) return 5; } - private int GetPropertyVisibilityRank(PropertyInfo property) + private static int GetPropertyVisibilityRank(PropertyInfo property) { var setter = property.SetMethod; if (setter.IsPublic) @@ -226,7 +252,7 @@ private int GetPropertyVisibilityRank(PropertyInfo property) return 5; } - private Dictionary> GetMapByName(IEnumerable> members, StringComparer comparer) where T : MemberInfo + private static Dictionary> GetMapByName(IEnumerable> members, StringComparer comparer) where T : MemberInfo { return members .GroupBy(m => m.Member.Name, @@ -249,7 +275,6 @@ private struct RankedMember where T : MemberInfo public int VisibilityRank; } - [Serializable] private struct NamedMember where T : MemberInfo { public NamedMember(string name, T[] members) diff --git a/src/NHibernate/Tuple/Component/PocoComponentTuplizer.cs b/src/NHibernate/Tuple/Component/PocoComponentTuplizer.cs index e94b6afc265..d1c7c88422c 100644 --- a/src/NHibernate/Tuple/Component/PocoComponentTuplizer.cs +++ b/src/NHibernate/Tuple/Component/PocoComponentTuplizer.cs @@ -2,6 +2,7 @@ using NHibernate.Bytecode; using NHibernate.Intercept; using NHibernate.Properties; +using NHibernate.Util; namespace NHibernate.Tuple.Component { @@ -11,25 +12,33 @@ namespace NHibernate.Tuple.Component /// A specific to the POCO entity mode. /// [Serializable] - public class PocoComponentTuplizer : AbstractComponentTuplizer + public class PocoComponentTuplizer : AbstractComponentTuplizer, IDeserializationCallback { - private readonly System.Type componentClass; - private readonly ISetter parentSetter; - private readonly IGetter parentGetter; [NonSerialized] - private IReflectionOptimizer optimizer; + private System.Type _componentClass; + private SerializableSystemType _serializableComponentClass; + private readonly ISetter _parentSetter; + private readonly IGetter _parentGetter; + [NonSerialized] + private IReflectionOptimizer _optimizer; + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableComponentClass = SerializableSystemType.Wrap(_componentClass); + } - [OnDeserialized] - internal void OnDeserialized(StreamingContext context) + void IDeserializationCallback.OnDeserialization(object sender) { + _componentClass = _serializableComponentClass?.GetSystemType(); SetReflectionOptimizer(); - if (optimizer != null) + if (_optimizer != null) { // Fix for NH-3119: // Also set the InstantiationOptimizer on the deserialized PocoInstantiator. - ((PocoInstantiator)instantiator).SetOptimizer(optimizer.InstantiationOptimizer); + ((PocoInstantiator)instantiator).SetOptimizer(_optimizer.InstantiationOptimizer); } ClearOptimizerWhenUsingCustomAccessors(); @@ -38,18 +47,18 @@ internal void OnDeserialized(StreamingContext context) public PocoComponentTuplizer(Mapping.Component component) : base(component) { - componentClass = component.ComponentClass; + _componentClass = component.ComponentClass; var parentProperty = component.ParentProperty; if (parentProperty == null) { - parentSetter = null; - parentGetter = null; + _parentSetter = null; + _parentGetter = null; } else { - parentSetter = parentProperty.GetSetter(componentClass); - parentGetter = parentProperty.GetGetter(componentClass); + _parentSetter = parentProperty.GetSetter(_componentClass); + _parentGetter = parentProperty.GetGetter(_componentClass); } SetReflectionOptimizer(); @@ -60,10 +69,7 @@ public PocoComponentTuplizer(Mapping.Component component) ClearOptimizerWhenUsingCustomAccessors(); } - public override System.Type MappedClass - { - get { return componentClass; } - } + public override System.Type MappedClass => _componentClass; public override object[] GetPropertyValues(object component) { @@ -73,9 +79,9 @@ public override object[] GetPropertyValues(object component) return new object[propertySpan]; } - if (optimizer != null && optimizer.AccessOptimizer != null) + if (_optimizer != null && _optimizer.AccessOptimizer != null) { - return optimizer.AccessOptimizer.GetPropertyValues(component); + return _optimizer.AccessOptimizer.GetPropertyValues(component); } else { @@ -85,9 +91,9 @@ public override object[] GetPropertyValues(object component) public override void SetPropertyValues(object component, object[] values) { - if (optimizer != null && optimizer.AccessOptimizer != null) + if (_optimizer != null && _optimizer.AccessOptimizer != null) { - optimizer.AccessOptimizer.SetPropertyValues(component, values); + _optimizer.AccessOptimizer.SetPropertyValues(component, values); } else { @@ -97,17 +103,17 @@ public override void SetPropertyValues(object component, object[] values) public override object GetParent(object component) { - return parentGetter.Get(component); + return _parentGetter.Get(component); } public override void SetParent(object component, object parent, Engine.ISessionFactoryImplementor factory) { - parentSetter.Set(component, parent); + _parentSetter.Set(component, parent); } public override bool HasParentProperty { - get { return parentGetter != null; } + get { return _parentGetter != null; } } protected internal override IInstantiator BuildInstantiator(Mapping.Component component) @@ -118,13 +124,13 @@ protected internal override IInstantiator BuildInstantiator(Mapping.Component co // return new ProxiedInstantiator(component); //} - if (optimizer == null) + if (_optimizer == null) { return new PocoInstantiator(component, null); } else { - return new PocoInstantiator(component, optimizer.InstantiationOptimizer); + return new PocoInstantiator(component, _optimizer.InstantiationOptimizer); } } @@ -142,7 +148,7 @@ protected void SetReflectionOptimizer() { if (Cfg.Environment.UseReflectionOptimizer) { - optimizer = Cfg.Environment.BytecodeProvider.GetReflectionOptimizer(componentClass, getters, setters); + _optimizer = Cfg.Environment.BytecodeProvider.GetReflectionOptimizer(_componentClass, getters, setters); } } @@ -150,7 +156,7 @@ protected void ClearOptimizerWhenUsingCustomAccessors() { if (hasCustomAccessors) { - optimizer = null; + _optimizer = null; } } } diff --git a/src/NHibernate/Tuple/PocoInstantiator.cs b/src/NHibernate/Tuple/PocoInstantiator.cs index 5085b194880..33330b15f02 100644 --- a/src/NHibernate/Tuple/PocoInstantiator.cs +++ b/src/NHibernate/Tuple/PocoInstantiator.cs @@ -15,21 +15,26 @@ public class PocoInstantiator : IInstantiator, IDeserializationCallback { private static readonly INHibernateLogger log = NHibernateLogger.For(typeof(PocoInstantiator)); - private readonly System.Type mappedClass; + [NonSerialized] + private System.Type _mappedClass; + private SerializableSystemType _serializableMappedClass; [NonSerialized] - private IInstantiationOptimizer optimizer; + private IInstantiationOptimizer _optimizer; - private readonly IProxyFactory proxyFactory; + [NonSerialized] + private readonly IProxyFactory _proxyFactory; - private readonly bool generateFieldInterceptionProxy; + private readonly bool _generateFieldInterceptionProxy; - private readonly bool embeddedIdentifier; + private readonly bool _embeddedIdentifier; [NonSerialized] - private ConstructorInfo constructor; + private ConstructorInfo _constructor; - private readonly System.Type proxyInterface; + [NonSerialized] + private System.Type _proxyInterface; + private SerializableSystemType _serializableProxyInterface; public PocoInstantiator() { @@ -37,40 +42,40 @@ public PocoInstantiator() public PocoInstantiator(Mapping.Component component, IInstantiationOptimizer optimizer) { - mappedClass = component.ComponentClass; - this.optimizer = optimizer; + _mappedClass = component.ComponentClass; + _optimizer = optimizer; - proxyInterface = null; - embeddedIdentifier = false; + _proxyInterface = null; + _embeddedIdentifier = false; try { - constructor = ReflectHelper.GetDefaultConstructor(mappedClass); + _constructor = ReflectHelper.GetDefaultConstructor(_mappedClass); } catch (PropertyNotFoundException) { - log.Info("no default (no-argument) constructor for class: {0} (class must be instantiated by Interceptor)", mappedClass.FullName); - constructor = null; + log.Info("no default (no-argument) constructor for class: {0} (class must be instantiated by Interceptor)", _mappedClass.FullName); + _constructor = null; } } public PocoInstantiator(PersistentClass persistentClass, IInstantiationOptimizer optimizer, IProxyFactory proxyFactory, bool generateFieldInterceptionProxy) { - mappedClass = persistentClass.MappedClass; - proxyInterface = persistentClass.ProxyInterface; - embeddedIdentifier = persistentClass.HasEmbeddedIdentifier; - this.optimizer = optimizer; - this.proxyFactory = proxyFactory; - this.generateFieldInterceptionProxy = generateFieldInterceptionProxy; + _mappedClass = persistentClass.MappedClass; + _proxyInterface = persistentClass.ProxyInterface; + _embeddedIdentifier = persistentClass.HasEmbeddedIdentifier; + _optimizer = optimizer; + _proxyFactory = proxyFactory; + _generateFieldInterceptionProxy = generateFieldInterceptionProxy; try { - constructor = ReflectHelper.GetDefaultConstructor(mappedClass); + _constructor = ReflectHelper.GetDefaultConstructor(_mappedClass); } catch (PropertyNotFoundException) { - log.Info("no default (no-argument) constructor for class: {0} (class must be instantiated by Interceptor)", mappedClass.FullName); - constructor = null; + log.Info("no default (no-argument) constructor for class: {0} (class must be instantiated by Interceptor)", _mappedClass.FullName); + _constructor = null; } } @@ -78,66 +83,80 @@ public PocoInstantiator(PersistentClass persistentClass, IInstantiationOptimizer public object Instantiate(object id) { - bool useEmbeddedIdentifierInstanceAsEntity = embeddedIdentifier && id != null && id.GetType().Equals(mappedClass); + bool useEmbeddedIdentifierInstanceAsEntity = _embeddedIdentifier && id != null && id.GetType().Equals(_mappedClass); return useEmbeddedIdentifierInstanceAsEntity ? id : Instantiate(); } public object Instantiate() { - if (ReflectHelper.IsAbstractClass(mappedClass)) + if (ReflectHelper.IsAbstractClass(_mappedClass)) { - throw new InstantiationException("Cannot instantiate abstract class or interface: ", mappedClass); + throw new InstantiationException("Cannot instantiate abstract class or interface: ", _mappedClass); } - if (generateFieldInterceptionProxy) + if (_generateFieldInterceptionProxy) { - return proxyFactory.GetFieldInterceptionProxy(GetInstance()); + return _proxyFactory.GetFieldInterceptionProxy(GetInstance()); } return GetInstance(); } private object GetInstance() { - if (optimizer != null) + if (_optimizer != null) { - return optimizer.CreateInstance(); + return _optimizer.CreateInstance(); } - if (mappedClass.IsValueType) + if (_mappedClass.IsValueType) { - return Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(mappedClass, true); + return Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(_mappedClass, true); } - if (constructor == null) + if (_constructor == null) { - throw new InstantiationException("No default constructor for entity: ", mappedClass); + throw new InstantiationException("No default constructor for entity: ", _mappedClass); } try { - return constructor.Invoke(null); + return _constructor.Invoke(null); } catch (Exception e) { - throw new InstantiationException("Could not instantiate entity: ", e, mappedClass); + throw new InstantiationException("Could not instantiate entity: ", e, _mappedClass); } } public bool IsInstance(object obj) { - return mappedClass.IsInstanceOfType(obj) || (proxyInterface != null && proxyInterface.IsInstanceOfType(obj)); //this one needed only for guessEntityMode() + return _mappedClass.IsInstanceOfType(obj) || (_proxyInterface != null && _proxyInterface.IsInstanceOfType(obj)); //this one needed only for guessEntityMode() } #endregion + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableMappedClass = SerializableSystemType.Wrap(_mappedClass); + _serializableProxyInterface = SerializableSystemType.Wrap(_proxyInterface); + } + #region IDeserializationCallback Members public void OnDeserialization(object sender) { - constructor = ReflectHelper.GetDefaultConstructor(mappedClass); + if (_generateFieldInterceptionProxy) + { + throw new InvalidOperationException("IProxyFactory implementors are currently not serializable."); + } + + _mappedClass = _serializableMappedClass?.GetSystemType(); + _proxyInterface = _serializableProxyInterface?.GetSystemType(); + _constructor = ReflectHelper.GetDefaultConstructor(_mappedClass); } #endregion public void SetOptimizer(IInstantiationOptimizer optimizer) { - this.optimizer = optimizer; + _optimizer = optimizer; } } } diff --git a/src/NHibernate/Type/AbstractEnumType.cs b/src/NHibernate/Type/AbstractEnumType.cs index 0b6ab128392..a5d5a485869 100644 --- a/src/NHibernate/Type/AbstractEnumType.cs +++ b/src/NHibernate/Type/AbstractEnumType.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Runtime.Serialization; using System.Text; using NHibernate.SqlTypes; +using NHibernate.Util; namespace NHibernate.Type { @@ -17,29 +19,40 @@ protected AbstractEnumType(SqlType sqlType,System.Type enumType) { if (enumType.IsEnum) { - this.enumType = enumType; + _enumType = enumType; } else { throw new MappingException(enumType.Name + " did not inherit from System.Enum"); } - defaultValue = Enum.ToObject(enumType, 0); + _defaultValue = Enum.ToObject(enumType, 0); } - private readonly object defaultValue; - private readonly System.Type enumType; + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableEnumType = SerializableSystemType.Wrap(_enumType); + } - public override System.Type ReturnedClass + [OnDeserialized] + private void OnDeserialized(StreamingContext context) { - get { return enumType; } + _enumType = _serializableEnumType?.GetSystemType(); } + private readonly object _defaultValue; + [NonSerialized] + private System.Type _enumType; + private SerializableSystemType _serializableEnumType; + + public override System.Type ReturnedClass => _enumType; + #region IIdentifierType Members public object StringToObject(string xml) { - return Enum.Parse(enumType, xml); + return Enum.Parse(_enumType, xml); } #endregion @@ -50,14 +63,8 @@ public override object FromStringValue(string xml) return StringToObject(xml); } - public override System.Type PrimitiveClass - { - get { return this.enumType; } - } + public override System.Type PrimitiveClass => _enumType; - public override object DefaultValue - { - get { return defaultValue; } - } + public override object DefaultValue => _defaultValue; } } diff --git a/src/NHibernate/Type/ArrayType.cs b/src/NHibernate/Type/ArrayType.cs index 1e9df6180fe..005065d74d9 100644 --- a/src/NHibernate/Type/ArrayType.cs +++ b/src/NHibernate/Type/ArrayType.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Data.Common; +using System.Runtime.Serialization; using NHibernate.Collection; using NHibernate.Engine; using NHibernate.Persister.Collection; @@ -16,8 +17,12 @@ namespace NHibernate.Type [Serializable] public partial class ArrayType : CollectionType { - private readonly System.Type elementClass; - private readonly System.Type arrayClass; + [NonSerialized] + private System.Type _elementClass; + private SerializableSystemType _serializableElementClass; + [NonSerialized] + private System.Type _arrayClass; + private SerializableSystemType _serializableArrayClass; /// /// Initializes a new instance of a class for @@ -34,17 +39,28 @@ public partial class ArrayType : CollectionType public ArrayType(string role, string propertyRef, System.Type elementClass) : base(role, propertyRef) { - this.elementClass = elementClass; - arrayClass = Array.CreateInstance(elementClass, 0).GetType(); + _elementClass = elementClass; + _arrayClass = Array.CreateInstance(elementClass, 0).GetType(); + } + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableElementClass = SerializableSystemType.Wrap(_elementClass); + _serializableArrayClass = SerializableSystemType.Wrap(_arrayClass); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + _elementClass = _serializableElementClass?.GetSystemType(); + _arrayClass = _serializableArrayClass?.GetSystemType(); } /// /// The for the element. /// - public override System.Type ReturnedClass - { - get { return arrayClass; } - } + public override System.Type ReturnedClass => _arrayClass; public override IPersistentCollection Instantiate(ISessionImplementor session, ICollectionPersister persister, object key) { @@ -82,17 +98,14 @@ public override IPersistentCollection Wrap(ISessionImplementor session, object a } /// - public override bool IsArrayType - { - get { return true; } - } + public override bool IsArrayType => true; // Not ported - ToString( object value, ISessionFactoryImplementor factory ) // - PesistentCollectionType implementation is able to handle arrays too in .NET public override object InstantiateResult(object original) { - return Array.CreateInstance(elementClass, ((Array) original).Length); + return Array.CreateInstance(_elementClass, ((Array) original).Length); } public override object Instantiate(int anticipatedSize) @@ -161,4 +174,4 @@ public override string ToLoggableString(object value, ISessionFactoryImplementor return CollectionPrinter.ToString(list); } } -} \ No newline at end of file +} diff --git a/src/NHibernate/Type/EntityType.cs b/src/NHibernate/Type/EntityType.cs index 60fcde67cd0..06cf3f7d2f4 100644 --- a/src/NHibernate/Type/EntityType.cs +++ b/src/NHibernate/Type/EntityType.cs @@ -8,6 +8,7 @@ using NHibernate.Proxy; using NHibernate.Util; using System.Collections.Generic; +using System.Runtime.Serialization; namespace NHibernate.Type { @@ -22,10 +23,12 @@ public abstract partial class EntityType : AbstractType, IAssociationType protected readonly string uniqueKeyPropertyName; private readonly string _uniqueKeyPropertyName; - private readonly bool eager; - private readonly string associatedEntityName; - private readonly bool unwrapProxy; - private System.Type returnedClass; + private readonly bool _eager; + private readonly string _associatedEntityName; + private readonly bool _unwrapProxy; + [NonSerialized] + private System.Type _returnedClass; + private SerializableSystemType _serializableReturnedClass; /// Constructs the requested entity type mapping. /// The name of the associated entity. @@ -45,22 +48,31 @@ protected internal EntityType(string entityName, string uniqueKeyPropertyName, b this.uniqueKeyPropertyName = uniqueKeyPropertyName; #pragma warning restore 618 - associatedEntityName = entityName; + _associatedEntityName = entityName; _uniqueKeyPropertyName = uniqueKeyPropertyName; - this.eager = eager; - this.unwrapProxy = unwrapProxy; + _eager = eager; + _unwrapProxy = unwrapProxy; } - /// Explicitly, an entity type is an entity type - /// True. - public override sealed bool IsEntityType + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableReturnedClass = SerializableSystemType.Wrap(_returnedClass); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) { - get { return true; } + _returnedClass = _serializableReturnedClass?.GetSystemType(); } + /// Explicitly, an entity type is an entity type + /// True. + public sealed override bool IsEntityType => true; + public override bool IsEqual(object x, object y, ISessionFactoryImplementor factory) { - IEntityPersister persister = factory.GetEntityPersister(associatedEntityName); + IEntityPersister persister = factory.GetEntityPersister(_associatedEntityName); if (!persister.CanExtractIdOutOfEntity) { return base.IsEqual(x, y); @@ -120,15 +132,15 @@ public override object NullSafeGet(DbDataReader rs, string name, ISessionImpleme /// entity persister (nor to the session factory, to look it up) which is really /// needed to "do the right thing" here... /// - override public System.Type ReturnedClass + public override System.Type ReturnedClass { get { - if (returnedClass == null) + if (_returnedClass == null) { - returnedClass = DetermineAssociatedEntityClass(); + _returnedClass = DetermineAssociatedEntityClass(); } - return returnedClass; + return _returnedClass; } } @@ -195,8 +207,8 @@ public override string ToLoggableString(object value, ISessionFactoryImplementor return "null"; } - IEntityPersister persister = factory.GetEntityPersister(associatedEntityName); - StringBuilder result = new StringBuilder().Append(associatedEntityName); + IEntityPersister persister = factory.GetEntityPersister(_associatedEntityName); + StringBuilder result = new StringBuilder().Append(_associatedEntityName); if (persister.HasIdentifierProperty) { @@ -208,20 +220,14 @@ public override string ToLoggableString(object value, ISessionFactoryImplementor return result.ToString(); } - public override string Name - { - get { return associatedEntityName; } - } + public override string Name => _associatedEntityName; public override object DeepCopy(object value, ISessionFactoryImplementor factory) { return value; //special case ... this is the leaf of the containment graph, even though not immutable } - public override bool IsMutable - { - get { return false; } - } + public override bool IsMutable => false; public abstract bool IsOneToOne { get; } @@ -247,9 +253,9 @@ public override object Replace(object original, object target, ISessionImplement { return target; } - if (session.GetContextEntityIdentifier(original) == null && ForeignKeys.IsTransientFast(associatedEntityName, original, session).GetValueOrDefault()) + if (session.GetContextEntityIdentifier(original) == null && ForeignKeys.IsTransientFast(_associatedEntityName, original, session).GetValueOrDefault()) { - object copy = session.Factory.GetEntityPersister(associatedEntityName).Instantiate(null); + object copy = session.Factory.GetEntityPersister(_associatedEntityName).Instantiate(null); //TODO: should this be Session.instantiate(Persister, ...)? copyCache.Add(original, copy); return copy; @@ -267,10 +273,7 @@ public override object Replace(object original, object target, ISessionImplement } } - public override bool IsAssociationType - { - get { return true; } - } + public override bool IsAssociationType => true; /// /// Converts the id contained in the to an object. @@ -282,7 +285,7 @@ public override bool IsAssociationType /// /// An instance of the object or if the identifer was null. /// - public override sealed object NullSafeGet(DbDataReader rs, string[] names, ISessionImplementor session, object owner) + public sealed override object NullSafeGet(DbDataReader rs, string[] names, ISessionImplementor session, object owner) { return ResolveIdentifier(Hydrate(rs, names, session, owner), session, owner); } @@ -301,7 +304,7 @@ public bool IsUniqueKeyReference /// The associated joinable public IJoinable GetAssociatedJoinable(ISessionFactoryImplementor factory) { - return (IJoinable) factory.GetEntityPersister(associatedEntityName); + return (IJoinable) factory.GetEntityPersister(_associatedEntityName); } /// @@ -367,10 +370,10 @@ internal virtual IType GetIdentifierType(ISessionImplementor session) protected object ResolveIdentifier(object id, ISessionImplementor session) { string entityName = GetAssociatedEntityName(); - bool isProxyUnwrapEnabled = unwrapProxy && session.Factory + bool isProxyUnwrapEnabled = _unwrapProxy && session.Factory .GetEntityPersister(entityName).IsInstrumented; - object proxyOrEntity = session.InternalLoad(entityName, id, eager, IsNullable && !isProxyUnwrapEnabled); + object proxyOrEntity = session.InternalLoad(entityName, id, _eager, IsNullable && !isProxyUnwrapEnabled); if (proxyOrEntity.IsProxy()) { @@ -394,21 +397,19 @@ public override object ResolveIdentifier(object value, ISessionImplementor sessi { return null; } - else + + if (IsNull(owner, session)) { - if (IsNull(owner, session)) - { - return null; //EARLY EXIT! - } + return null; //EARLY EXIT! + } - if (IsReferenceToPrimaryKey) - { - return ResolveIdentifier(value, session); - } - else - { - return LoadByUniqueKey(GetAssociatedEntityName(), _uniqueKeyPropertyName, value, session); - } + if (IsReferenceToPrimaryKey) + { + return ResolveIdentifier(value, session); + } + else + { + return LoadByUniqueKey(GetAssociatedEntityName(), _uniqueKeyPropertyName, value, session); } } @@ -424,7 +425,7 @@ public virtual string GetAssociatedEntityName(ISessionFactoryImplementor factory /// The associated entity name. public string GetAssociatedEntityName() { - return associatedEntityName; + return _associatedEntityName; } /// @@ -439,24 +440,15 @@ public string GetAssociatedEntityName() /// public abstract bool UseLHSPrimaryKey { get; } - public string LHSPropertyName - { - get { return null; } - } + public string LHSPropertyName => null; - public string RHSUniqueKeyPropertyName - { - get { return _uniqueKeyPropertyName; } - } + public string RHSUniqueKeyPropertyName => _uniqueKeyPropertyName; - public virtual string PropertyName - { - get { return null; } - } + public virtual string PropertyName => null; public override int GetHashCode(object x, ISessionFactoryImplementor factory) { - IEntityPersister persister = factory.GetEntityPersister(associatedEntityName); + IEntityPersister persister = factory.GetEntityPersister(_associatedEntityName); if (!persister.CanExtractIdOutOfEntity) { return base.GetHashCode(x); @@ -478,10 +470,7 @@ public override int GetHashCode(object x, ISessionFactoryImplementor factory) public abstract bool IsAlwaysDirtyChecked { get; } - public bool IsReferenceToPrimaryKey - { - get { return string.IsNullOrEmpty(_uniqueKeyPropertyName); } - } + public bool IsReferenceToPrimaryKey => string.IsNullOrEmpty(_uniqueKeyPropertyName); public string GetOnCondition(string alias, ISessionFactoryImplementor factory, IDictionary enabledFilters) { @@ -498,7 +487,7 @@ public string GetOnCondition(string alias, ISessionFactoryImplementor factory, I public override IType GetSemiResolvedType(ISessionFactoryImplementor factory) { - return factory.GetEntityPersister(associatedEntityName).IdentifierType; + return factory.GetEntityPersister(_associatedEntityName).IdentifierType; } /// diff --git a/src/NHibernate/Type/SerializableType.cs b/src/NHibernate/Type/SerializableType.cs index 3be7ad710db..923a2538918 100644 --- a/src/NHibernate/Type/SerializableType.cs +++ b/src/NHibernate/Type/SerializableType.cs @@ -6,6 +6,7 @@ using System.Runtime.Serialization.Formatters.Binary; using NHibernate.Engine; using NHibernate.SqlTypes; +using NHibernate.Util; namespace NHibernate.Type { @@ -28,8 +29,10 @@ namespace NHibernate.Type [Serializable] public partial class SerializableType : MutableType { - private readonly System.Type serializableClass; - private readonly BinaryType binaryType; + [NonSerialized] + private System.Type _serializableClass; + private SerializableSystemType _serializableSerializableClass; + private readonly BinaryType _binaryType; internal SerializableType() : this(typeof(Object)) { @@ -37,19 +40,31 @@ internal SerializableType() : this(typeof(Object)) internal SerializableType(System.Type serializableClass) : base(new BinarySqlType()) { - this.serializableClass = serializableClass; - binaryType = (BinaryType) NHibernateUtil.Binary; + _serializableClass = serializableClass; + _binaryType = NHibernateUtil.Binary; } internal SerializableType(System.Type serializableClass, BinarySqlType sqlType) : base(sqlType) { - this.serializableClass = serializableClass; - binaryType = (BinaryType) TypeFactory.GetBinaryType(sqlType.Length); + _serializableClass = serializableClass; + _binaryType = (BinaryType) TypeFactory.GetBinaryType(sqlType.Length); + } + + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializableSerializableClass = SerializableSystemType.Wrap(_serializableClass); + } + + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + _serializableClass = _serializableSerializableClass?.GetSystemType(); } public override void Set(DbCommand st, object value, int index, ISessionImplementor session) { - binaryType.Set(st, ToBytes(value), index, session); + _binaryType.Set(st, ToBytes(value), index, session); } public override object Get(DbDataReader rs, string name, ISessionImplementor session) @@ -59,7 +74,7 @@ public override object Get(DbDataReader rs, string name, ISessionImplementor ses public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - byte[] bytes = (byte[]) binaryType.Get(rs, index, session); + byte[] bytes = (byte[]) _binaryType.Get(rs, index, session); if (bytes == null) { return null; @@ -70,10 +85,7 @@ public override object Get(DbDataReader rs, int index, ISessionImplementor sessi } } - public override System.Type ReturnedClass - { - get { return serializableClass; } - } + public override System.Type ReturnedClass => _serializableClass; public override bool IsEqual(object x, object y) { @@ -83,22 +95,22 @@ public override bool IsEqual(object x, object y) if (x == null || y == null) return false; - return x.Equals(y) || binaryType.IsEqual(ToBytes(x), ToBytes(y)); + return x.Equals(y) || _binaryType.IsEqual(ToBytes(x), ToBytes(y)); } public override int GetHashCode(Object x) { - return binaryType.GetHashCode(ToBytes(x)); + return _binaryType.GetHashCode(ToBytes(x)); } public override string ToString(object value) { - return binaryType.ToString(ToBytes(value)); + return _binaryType.ToString(ToBytes(value)); } public override object FromStringValue(string xml) { - return FromBytes((byte[])binaryType.FromStringValue(xml)); + return FromBytes((byte[])_binaryType.FromStringValue(xml)); } /// @@ -106,7 +118,7 @@ public override string Name { get { - return serializableClass == typeof(ISerializable) ? "serializable" : serializableClass.FullName; + return _serializableClass == typeof(ISerializable) ? "serializable" : _serializableClass.FullName; } } @@ -163,4 +175,4 @@ public override object Disassemble(object value, ISessionImplementor session, ob return (value == null) ? null : ToBytes(value); } } -} \ No newline at end of file +} diff --git a/src/NHibernate/UnresolvableObjectException.cs b/src/NHibernate/UnresolvableObjectException.cs index d766bf2881a..c66947193d5 100644 --- a/src/NHibernate/UnresolvableObjectException.cs +++ b/src/NHibernate/UnresolvableObjectException.cs @@ -3,6 +3,7 @@ using System.Security; using System.Security.Permissions; using NHibernate.Impl; +using NHibernate.Util; namespace NHibernate { @@ -13,9 +14,10 @@ namespace NHibernate [Serializable] public class UnresolvableObjectException : HibernateException { - private readonly object identifier; - private readonly System.Type clazz; - private readonly string entityName; + private readonly object _identifier; + [NonSerialized] + private readonly System.Type _clazz; + private readonly string _entityName; /// /// Initializes a new instance of the class. @@ -39,40 +41,24 @@ public UnresolvableObjectException(object identifier, string entityName) public UnresolvableObjectException(string message, object identifier, System.Type clazz) : base(message) { - this.identifier = identifier; - this.clazz = clazz; + _identifier = identifier; + _clazz = clazz; } public UnresolvableObjectException(string message, object identifier, string entityName) : base(message) { - this.identifier = identifier; - this.entityName = entityName; + _identifier = identifier; + _entityName = entityName; } - public object Identifier - { - get { return identifier; } - } + public object Identifier => _identifier; - public override string Message - { - get { return base.Message + MessageHelper.InfoString(EntityName, identifier); } - } + public override string Message => base.Message + MessageHelper.InfoString(EntityName, _identifier); - public System.Type PersistentClass - { - get { return clazz; } - } + public System.Type PersistentClass => _clazz; - public string EntityName - { - get - { - if (clazz != null) return clazz.FullName; - return entityName; - } - } + public string EntityName => _clazz != null ? _clazz.FullName : _entityName; public static void ThrowIfNull(object o, object id, System.Type clazz) { @@ -96,17 +82,17 @@ public static void ThrowIfNull(object o, object id, string entityName) public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); - info.AddValue("identifier", identifier); - info.AddValue("clazz", clazz); - info.AddValue("entityName", entityName); + info.AddValue("identifier", _identifier); + info.AddValue("clazz", ObjectReferenceSystemType.Wrap(_clazz, true)); + info.AddValue("entityName", _entityName); } protected UnresolvableObjectException(SerializationInfo info, StreamingContext context) : base(info, context) { - identifier = info.GetValue("identifier", typeof(object)); - clazz = info.GetValue("clazz", typeof(System.Type)) as System.Type; - entityName = info.GetString("entityName"); + _identifier = info.GetValue("identifier", typeof(object)); + _entityName = info.GetString("entityName"); + _clazz = info.GetValue("clazz"); } #endregion