Skip to content

Commit fff308f

Browse files
committed
Implement helpers to serialize system types in preparation for .NET Core.
Serialize System.Type, ConstructorInfo, FieldInfo, MethodInfo, and PropertyInfo using only basic types.
1 parent 73797df commit fff308f

9 files changed

+553
-25
lines changed

src/NHibernate/Util/AssemblyQualifiedTypeName.cs

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,26 @@
22

33
namespace NHibernate.Util
44
{
5+
[Serializable]
56
public class AssemblyQualifiedTypeName
67
{
7-
private readonly string type;
8-
private readonly string assembly;
9-
private readonly int hashCode;
8+
private readonly string _type;
9+
private readonly string _assembly;
10+
private readonly int _hashCode;
1011

1112
public AssemblyQualifiedTypeName(string type, string assembly)
1213
{
13-
if (type == null)
14-
{
15-
throw new ArgumentNullException("type");
16-
}
17-
this.type = type;
18-
this.assembly = assembly;
14+
_type = type ?? throw new ArgumentNullException(nameof(type));
15+
_assembly = assembly;
1916
unchecked
2017
{
21-
hashCode = (type.GetHashCode() * 397) ^ (assembly != null ? assembly.GetHashCode() : 0);
18+
_hashCode = (type.GetHashCode() * 397) ^ (assembly?.GetHashCode() ?? 0);
2219
}
2320
}
2421

25-
public string Type
26-
{
27-
get { return type; }
28-
}
22+
public string Type => _type;
2923

30-
public string Assembly
31-
{
32-
get { return assembly; }
33-
}
24+
public string Assembly => _assembly;
3425

3526
public override bool Equals(object obj)
3627
{
@@ -40,12 +31,12 @@ public override bool Equals(object obj)
4031

4132
public override string ToString()
4233
{
43-
if (assembly == null)
34+
if (_assembly == null)
4435
{
45-
return type;
36+
return _type;
4637
}
4738

48-
return string.Concat(type, ", ", assembly);
39+
return string.Concat(_type, ", ", _assembly);
4940
}
5041

5142
public bool Equals(AssemblyQualifiedTypeName obj)
@@ -58,12 +49,12 @@ public bool Equals(AssemblyQualifiedTypeName obj)
5849
{
5950
return true;
6051
}
61-
return Equals(obj.type, type) && Equals(obj.assembly, assembly);
52+
return Equals(obj._type, _type) && Equals(obj._assembly, _assembly);
6253
}
6354

6455
public override int GetHashCode()
6556
{
66-
return hashCode;
57+
return _hashCode;
6758
}
6859
}
69-
}
60+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System.Reflection;
2+
3+
namespace NHibernate.Util
4+
{
5+
internal interface ISerializableMemberInfo
6+
{
7+
MemberInfo Value { get; }
8+
}
9+
}

src/NHibernate/Util/ReflectHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ public static System.Type TypeFromAssembly(string type, string assembly, bool th
392392
/// type cannot be found then the assembly is loaded using
393393
/// <see cref="Assembly.Load(string)" />.
394394
/// </remarks>
395-
public static System.Type TypeFromAssembly(AssemblyQualifiedTypeName name, bool throwOnError)
395+
public static System.Type TypeFromAssembly(this AssemblyQualifiedTypeName name, bool throwOnError)
396396
{
397397
try
398398
{
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using System;
2+
using System.Linq;
3+
using System.Reflection;
4+
using System.Runtime.Serialization;
5+
using System.Security;
6+
7+
namespace NHibernate.Util
8+
{
9+
[Serializable]
10+
internal sealed class SerializableConstructorInfo : ISerializable
11+
{
12+
[NonSerialized]
13+
private readonly ConstructorInfo _constructorInfo;
14+
15+
/// <summary>
16+
/// Creates a new instance of <see cref="SerializableConstructorInfo"/> if
17+
/// <paramref name="constructorInfo"/> is not null, otherwise returns <c>null</c>.
18+
/// </summary>
19+
/// <param name="constructorInfo">The <see cref="ConstructorInfo"/> being wrapped for serialization.</param>
20+
/// <returns>New instance of <see cref="SerializableConstructorInfo"/> or <c>null</c>.</returns>
21+
public static SerializableConstructorInfo Wrap(ConstructorInfo constructorInfo)
22+
{
23+
return constructorInfo == null ? null : new SerializableConstructorInfo(constructorInfo);
24+
}
25+
26+
/// <summary>
27+
/// Creates a new <see cref="SerializableConstructorInfo"/>
28+
/// </summary>
29+
/// <param name="constructorInfo">The <see cref="ConstructorInfo"/> being wrapped for serialization.</param>
30+
private SerializableConstructorInfo(ConstructorInfo constructorInfo)
31+
{
32+
_constructorInfo = constructorInfo ?? throw new ArgumentNullException(nameof(constructorInfo));
33+
if (constructorInfo.DeclaringType == null)
34+
{
35+
throw new ArgumentException("ConstructorInfo must have non-null DeclaringType", nameof(constructorInfo));
36+
}
37+
}
38+
39+
private SerializableConstructorInfo(SerializationInfo info, StreamingContext context)
40+
{
41+
System.Type declaringType = info.GetValue<SerializableSystemType>("declaringType").GetType();
42+
SerializableSystemType[] parameterSystemTypes = info.GetValue<SerializableSystemType[]>("parameterTypesHelper");
43+
44+
System.Type[] parameterTypes = parameterSystemTypes?.Select(x => x.GetType()).ToArray() ?? new System.Type[0];
45+
_constructorInfo = declaringType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, parameterTypes, null);
46+
47+
if (_constructorInfo == null) throw new MissingMethodException(declaringType.FullName, ".ctor");
48+
}
49+
50+
[SecurityCritical]
51+
public void GetObjectData(SerializationInfo info, StreamingContext context)
52+
{
53+
SerializableSystemType[] parameterSystemTypes =
54+
_constructorInfo.GetParameters()
55+
.Select(x => SerializableSystemType.Wrap(x.ParameterType))
56+
.ToArray();
57+
58+
info.AddValue("declaringType", SerializableSystemType.Wrap(_constructorInfo.DeclaringType));
59+
info.AddValue("parameterTypesHelper", parameterSystemTypes);
60+
}
61+
62+
public ConstructorInfo Value => _constructorInfo;
63+
64+
private bool Equals(SerializableConstructorInfo other)
65+
{
66+
return Equals(_constructorInfo, other._constructorInfo);
67+
}
68+
69+
public override bool Equals(object obj)
70+
{
71+
if (ReferenceEquals(null, obj)) return false;
72+
if (ReferenceEquals(this, obj)) return true;
73+
return obj is SerializableConstructorInfo && Equals((SerializableConstructorInfo) obj);
74+
}
75+
76+
public override int GetHashCode()
77+
{
78+
return (_constructorInfo != null ? _constructorInfo.GetHashCode() : 0);
79+
}
80+
81+
public static bool operator ==(SerializableConstructorInfo left, SerializableConstructorInfo right)
82+
{
83+
return Equals(left, right);
84+
}
85+
86+
public static bool operator !=(SerializableConstructorInfo left, SerializableConstructorInfo right)
87+
{
88+
return !Equals(left, right);
89+
}
90+
91+
public static implicit operator ConstructorInfo(SerializableConstructorInfo serializableConstructorInfo)
92+
{
93+
return serializableConstructorInfo?.Value;
94+
}
95+
96+
public static explicit operator SerializableConstructorInfo(ConstructorInfo constructorInfo)
97+
{
98+
return Wrap(constructorInfo);
99+
}
100+
}
101+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
using System;
2+
using System.Reflection;
3+
using System.Runtime.Serialization;
4+
using System.Security;
5+
6+
namespace NHibernate.Util
7+
{
8+
[Serializable]
9+
internal sealed class SerializableFieldInfo : ISerializable, ISerializableMemberInfo
10+
{
11+
[NonSerialized]
12+
private readonly FieldInfo _fieldInfo;
13+
14+
/// <summary>
15+
/// Creates a new instance of <see cref="SerializableFieldInfo"/> if
16+
/// <paramref name="fieldInfo"/> is not null, otherwise returns <c>null</c>.
17+
/// </summary>
18+
/// <param name="fieldInfo">The <see cref="FieldInfo"/> being wrapped for serialization.</param>
19+
/// <returns>New instance of <see cref="SerializableFieldInfo"/> or <c>null</c>.</returns>
20+
public static SerializableFieldInfo Wrap(FieldInfo fieldInfo)
21+
{
22+
return fieldInfo == null ? null : new SerializableFieldInfo(fieldInfo);
23+
}
24+
25+
/// <summary>
26+
/// Creates a new <see cref="SerializableFieldInfo"/>
27+
/// </summary>
28+
/// <param name="fieldInfo">The <see cref="FieldInfo"/> being wrapped for serialization.</param>
29+
private SerializableFieldInfo(FieldInfo fieldInfo)
30+
{
31+
_fieldInfo = fieldInfo ?? throw new ArgumentNullException(nameof(fieldInfo));
32+
if (fieldInfo.IsStatic) throw new ArgumentException("Only for instance fields", nameof(fieldInfo));
33+
if (fieldInfo.DeclaringType == null) throw new ArgumentException("FieldInfo must have non-null DeclaringType", nameof(fieldInfo));
34+
}
35+
36+
private SerializableFieldInfo(SerializationInfo info, StreamingContext context)
37+
{
38+
System.Type declaringType = info.GetValue<SerializableSystemType>("declaringType").GetType();
39+
string fieldName = info.GetString("fieldName");
40+
41+
_fieldInfo = declaringType.GetField(
42+
fieldName,
43+
BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
44+
45+
if (_fieldInfo == null) throw new MissingFieldException(declaringType.FullName, fieldName);
46+
}
47+
48+
[SecurityCritical]
49+
public void GetObjectData(SerializationInfo info, StreamingContext context)
50+
{
51+
info.AddValue("declaringType", SerializableSystemType.Wrap(_fieldInfo.DeclaringType));
52+
info.AddValue("fieldName", _fieldInfo.Name);
53+
}
54+
55+
public FieldInfo Value => _fieldInfo;
56+
57+
MemberInfo ISerializableMemberInfo.Value => Value;
58+
59+
private bool Equals(SerializableFieldInfo other)
60+
{
61+
return Equals(_fieldInfo, other._fieldInfo);
62+
}
63+
64+
public override bool Equals(object obj)
65+
{
66+
if (ReferenceEquals(null, obj)) return false;
67+
if (ReferenceEquals(this, obj)) return true;
68+
return obj is SerializableFieldInfo && Equals((SerializableFieldInfo) obj);
69+
}
70+
71+
public override int GetHashCode()
72+
{
73+
return (_fieldInfo != null ? _fieldInfo.GetHashCode() : 0);
74+
}
75+
76+
public static bool operator ==(SerializableFieldInfo left, SerializableFieldInfo right)
77+
{
78+
return Equals(left, right);
79+
}
80+
81+
public static bool operator !=(SerializableFieldInfo left, SerializableFieldInfo right)
82+
{
83+
return !Equals(left, right);
84+
}
85+
86+
public static implicit operator FieldInfo(SerializableFieldInfo serializableFieldInfo)
87+
{
88+
return serializableFieldInfo?.Value;
89+
}
90+
91+
public static explicit operator SerializableFieldInfo(FieldInfo fieldInfo)
92+
{
93+
return Wrap(fieldInfo);
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)