Skip to content

Manually serialize system types in preparation for .NET Core. #1425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/NHibernate.Test/ExceptionsTest/SerializationFixture.cs
Original file line number Diff line number Diff line change
@@ -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()));
}
}
}
}
1 change: 1 addition & 0 deletions src/NHibernate/Async/Impl/CriteriaImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/NHibernate/Async/Type/ArrayType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -70,4 +71,4 @@ public override async Task<object> ReplaceElementsAsync(object original, object
return result;
}
}
}
}
39 changes: 19 additions & 20 deletions src/NHibernate/Async/Type/EntityType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using NHibernate.Proxy;
using NHibernate.Util;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace NHibernate.Type
{
Expand Down Expand Up @@ -65,12 +66,12 @@ protected internal async Task<object> 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);
Expand Down Expand Up @@ -98,9 +99,9 @@ public override async Task<object> 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;
Expand Down Expand Up @@ -129,7 +130,7 @@ public override async Task<object> ReplaceAsync(object original, object target,
/// <returns>
/// An instance of the object or <see langword="null" /> if the identifer was null.
/// </returns>
public override sealed async Task<object> NullSafeGetAsync(DbDataReader rs, string[] names, ISessionImplementor session, object owner, CancellationToken cancellationToken)
public sealed override async Task<object> 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);
Expand All @@ -144,10 +145,10 @@ protected async Task<object> 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())
{
Expand Down Expand Up @@ -178,21 +179,19 @@ public override Task<object> ResolveIdentifierAsync(object value, ISessionImplem
{
return Task.FromResult<object>(null);
}
else

if (IsNull(owner, session))
{
if (IsNull(owner, session))
{
return Task.FromResult<object>(null); //EARLY EXIT!
}
return Task.FromResult<object>(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)
Expand Down
3 changes: 2 additions & 1 deletion src/NHibernate/Async/Type/SerializableType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using System.Runtime.Serialization.Formatters.Binary;
using NHibernate.Engine;
using NHibernate.SqlTypes;
using NHibernate.Util;

namespace NHibernate.Type
{
Expand Down Expand Up @@ -56,4 +57,4 @@ public override Task<object> DisassembleAsync(object value, ISessionImplementor
}
}
}
}
}
24 changes: 17 additions & 7 deletions src/NHibernate/Engine/Query/QueryPlanCache.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -184,19 +185,16 @@ private class HQLQueryPlanKey : IEquatable<HQLQueryPlanKey>
private readonly bool shallow;
private readonly HashSet<string> filterNames;
private readonly int hashCode;
private readonly System.Type queryTypeDiscriminator;

public HQLQueryPlanKey(string query, bool shallow, IDictionary<string, IFilter> enabledFilters)
: this(typeof(object), query, shallow, enabledFilters)
{
}
[NonSerialized]
private System.Type queryTypeDiscriminator;
private SerializableSystemType _serializableQueryTypeDiscriminator;

public HQLQueryPlanKey(IQueryExpression queryExpression, bool shallow, IDictionary<string, IFilter> enabledFilters)
: this(queryExpression.GetType(), queryExpression.Key, shallow, enabledFilters)
{
}

protected HQLQueryPlanKey(System.Type queryTypeDiscriminator, string query, bool shallow, IDictionary<string, IFilter> enabledFilters)
private HQLQueryPlanKey(System.Type queryTypeDiscriminator, string query, bool shallow, IDictionary<string, IFilter> enabledFilters)
{
this.queryTypeDiscriminator = queryTypeDiscriminator;
this.query = query;
Expand All @@ -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);
Expand Down
17 changes: 16 additions & 1 deletion src/NHibernate/Impl/CriteriaImpl.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<CriterionEntry> criteria = new List<CriterionEntry>();
private readonly List<OrderEntry> orderEntries = new List<OrderEntry>(10);
private readonly Dictionary<string, FetchMode> fetchModes = new Dictionary<string, FetchMode>();
Expand Down Expand Up @@ -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; }
Expand Down
29 changes: 9 additions & 20 deletions src/NHibernate/InstantiationException.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Runtime.Serialization;
using System.Security;
using System.Security.Permissions;
using NHibernate.Util;

namespace NHibernate
{
Expand All @@ -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));
}

/// <summary>
Expand All @@ -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));
}

/// <summary>
/// Gets the <see cref="System.Type"/> that NHibernate was trying to instantiate.
/// </summary>
public System.Type PersistentType
{
get { return type; }
}
public System.Type PersistentType => _type;

/// <summary>
/// Gets a message that describes the current <see cref="InstantiationException"/>.
Expand All @@ -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.
/// </value>
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

Expand All @@ -76,7 +65,7 @@ public override string Message
/// </param>
protected InstantiationException(SerializationInfo info, StreamingContext context) : base(info, context)
{
this.type = info.GetValue("type", typeof(System.Type)) as System.Type;
_type = info.GetValue<System.Type>("type");
}

/// <summary>
Expand All @@ -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
Expand Down
18 changes: 17 additions & 1 deletion src/NHibernate/Intercept/AbstractFieldInterceptor.cs
Original file line number Diff line number Diff line change
@@ -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
{
Expand All @@ -16,7 +18,9 @@ public abstract class AbstractFieldInterceptor : IFieldInterceptor
private readonly ISet<string> unwrapProxyFieldNames;
private readonly HashSet<string> loadedUnwrapProxyFieldNames = new HashSet<string>();
private readonly string entityName;
private readonly System.Type mappedClass;
[NonSerialized]
private System.Type mappedClass;
private SerializableSystemType _serializableMappedClass;

[NonSerialized]
private bool initializing;
Expand All @@ -31,6 +35,18 @@ protected internal AbstractFieldInterceptor(ISessionImplementor session, ISet<st
this.mappedClass = mappedClass;
}

[OnSerializing]
private void OnSerializing(StreamingContext context)
{
_serializableMappedClass = SerializableSystemType.Wrap(mappedClass);
}

[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
mappedClass = _serializableMappedClass?.GetSystemType();
}

#region IFieldInterceptor Members

public bool IsDirty
Expand Down
Loading