Skip to content

Obsolete IDeserializationCallback from EntityKey #1977

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

Merged
merged 2 commits into from
Jan 16, 2019
Merged
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
32 changes: 13 additions & 19 deletions src/NHibernate/Engine/EntityKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
using System.Security;
using NHibernate.Impl;
using NHibernate.Persister.Entity;
using NHibernate.Type;

namespace NHibernate.Engine
{
//TODO 6.0: Remove IDeserializationCallback interface
/// <summary>
/// A globally unique identifier of an instance, consisting of the user-visible identifier
/// and the identifier space (eg. tablename)
Expand All @@ -17,15 +17,14 @@ public sealed class EntityKey : IDeserializationCallback, ISerializable, IEquata
private readonly object identifier;
private readonly IEntityPersister _persister;
// hashcode may vary among processes, they cannot be stored and have to be re-computed after deserialization
[NonSerialized]
private int? _hashCode;
private readonly int _hashCode;

/// <summary> Construct a unique identifier for an entity class instance</summary>
public EntityKey(object id, IEntityPersister persister)
{
identifier = id ?? throw new AssertionFailure("null identifier");
_persister = persister;
_hashCode = GenerateHashCode();
_hashCode = GenerateHashCode(persister, id);
}

private EntityKey(SerializationInfo info, StreamingContext context)
Expand All @@ -34,6 +33,7 @@ private EntityKey(SerializationInfo info, StreamingContext context)
var factory = (ISessionFactoryImplementor) info.GetValue(nameof(_persister.Factory), typeof(ISessionFactoryImplementor));
var entityName = (string) info.GetValue(nameof(EntityName), typeof(string));
_persister = factory.GetEntityPersister(entityName);
_hashCode = GenerateHashCode(_persister, identifier);
}

public bool IsBatchLoadable => _persister.IsBatchLoadable;
Expand Down Expand Up @@ -66,26 +66,16 @@ public bool Equals(EntityKey other)

public override int GetHashCode()
{
// If the object is put in a set or dictionary during deserialization, the hashcode will not yet be
// computed. Compute the hashcode on the fly. So long as this happens only during deserialization, there
// will be no thread safety issues. For the hashcode to be always defined after deserialization, the
// deserialization callback is used.
return _hashCode ?? GenerateHashCode();
return _hashCode;
}

/// <inheritdoc />
public void OnDeserialization(object sender)
{
_hashCode = GenerateHashCode();
}

private int GenerateHashCode()
private static int GenerateHashCode(IEntityPersister persister, object id)
{
int result = 17;
unchecked
{
result = 37 * result + RootEntityName.GetHashCode();
result = 37 * result + _persister.IdentifierType.GetHashCode(identifier, _persister.Factory);
result = 37 * result + persister.RootEntityName.GetHashCode();
result = 37 * result + persister.IdentifierType.GetHashCode(id, persister.Factory);
}
return result;
}
Expand All @@ -96,11 +86,15 @@ public override string ToString()
}

[SecurityCritical]
public void GetObjectData(SerializationInfo info, StreamingContext context)
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue(nameof(Identifier), identifier);
info.AddValue(nameof(_persister.Factory), _persister.Factory);
info.AddValue(nameof(EntityName), EntityName);
}

[Obsolete("IDeserializationCallback interface has no usages and will be removed in a future version")]
public void OnDeserialization(object sender)
{}
}
}