Skip to content

Commit 1cb6cf6

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 524d06a commit 1cb6cf6

8 files changed

+379
-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+
this._type = type ?? throw new ArgumentNullException(nameof(type));
15+
this._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+
}

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: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Linq;
4+
using System.Reflection;
5+
using System.Runtime.Serialization;
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+
public SerializableConstructorInfo(ConstructorInfo constructorInfo)
31+
{
32+
_constructorInfo = constructorInfo;
33+
if (constructorInfo != null && 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();
45+
this._constructorInfo = declaringType?.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, parameterTypes, null);
46+
}
47+
48+
public void GetObjectData(SerializationInfo info, StreamingContext context)
49+
{
50+
SerializableSystemType[] parameterSystemTypes =
51+
_constructorInfo?.GetParameters()
52+
.Select(x => new SerializableSystemType(x.ParameterType))
53+
.ToArray();
54+
55+
info.AddValueWithType("declaringType", SerializableSystemType.Wrap(_constructorInfo?.DeclaringType));
56+
info.AddValueWithType("parameterTypesHelper", parameterSystemTypes);
57+
}
58+
59+
public ConstructorInfo Value => _constructorInfo;
60+
}
61+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Reflection;
4+
using System.Runtime.Serialization;
5+
6+
namespace NHibernate.Util
7+
{
8+
[Serializable]
9+
internal sealed class SerializableFieldInfo : ISerializable
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+
public SerializableFieldInfo(FieldInfo fieldInfo)
30+
{
31+
_fieldInfo = fieldInfo;
32+
if (fieldInfo != null)
33+
{
34+
if (fieldInfo.IsStatic) throw new ArgumentException("Only for instance fields", nameof(fieldInfo));
35+
if (fieldInfo.DeclaringType == null)
36+
throw new ArgumentException("FieldInfo must have non-null DeclaringType", nameof(fieldInfo));
37+
}
38+
}
39+
40+
private SerializableFieldInfo(SerializationInfo info, StreamingContext context)
41+
{
42+
System.Type declaringType = info.GetValue<SerializableSystemType>("declaringType")?.GetType();
43+
string fieldName = info.GetString("fieldName");
44+
45+
this._fieldInfo = declaringType?.GetField(
46+
fieldName,
47+
BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
48+
}
49+
50+
public void GetObjectData(SerializationInfo info, StreamingContext context)
51+
{
52+
info.AddValueWithType("declaringType", SerializableSystemType.Wrap(_fieldInfo?.DeclaringType));
53+
info.AddValue("fieldName", _fieldInfo?.Name);
54+
}
55+
56+
public FieldInfo Value => _fieldInfo;
57+
58+
private bool Equals(SerializableFieldInfo other)
59+
{
60+
return Equals(_fieldInfo, other._fieldInfo);
61+
}
62+
63+
public override bool Equals(object obj)
64+
{
65+
if (ReferenceEquals(null, obj)) return false;
66+
if (ReferenceEquals(this, obj)) return true;
67+
if (ReferenceEquals(this._fieldInfo, obj)) return true;
68+
if (obj is SerializableFieldInfo) return Equals((SerializableFieldInfo) obj);
69+
return (obj is FieldInfo) && this._fieldInfo.Equals(obj);
70+
}
71+
72+
public override int GetHashCode()
73+
{
74+
return _fieldInfo.GetHashCode();
75+
}
76+
}
77+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Globalization;
4+
using System.Linq;
5+
using System.Reflection;
6+
using System.Runtime.Serialization;
7+
8+
namespace NHibernate.Util
9+
{
10+
[Serializable]
11+
internal sealed class SerializableMethodInfo : ISerializable
12+
{
13+
[NonSerialized]
14+
private readonly MethodInfo _methodInfo;
15+
16+
/// <summary>
17+
/// Creates a new instance of <see cref="SerializableMethodInfo"/> if
18+
/// <paramref name="methodInfo"/> is not null, otherwise returns <c>null</c>.
19+
/// </summary>
20+
/// <param name="methodInfo">The <see cref="MethodInfo"/> being wrapped for serialization.</param>
21+
/// <returns>New instance of <see cref="SerializableMethodInfo"/> or <c>null</c>.</returns>
22+
public static SerializableMethodInfo Wrap(MethodInfo methodInfo)
23+
{
24+
return methodInfo == null ? null : new SerializableMethodInfo(methodInfo);
25+
}
26+
27+
/// <summary>
28+
/// Creates a new <see cref="SerializableMethodInfo"/>
29+
/// </summary>
30+
/// <param name="methodInfo">The <see cref="MethodInfo"/> being wrapped for serialization.</param>
31+
public SerializableMethodInfo(MethodInfo methodInfo)
32+
{
33+
_methodInfo = methodInfo;
34+
if (methodInfo != null)
35+
{
36+
if (methodInfo.IsStatic) throw new ArgumentException("Only for instance fields", nameof(methodInfo));
37+
if (methodInfo.DeclaringType == null) throw new ArgumentException("MethodInfo must have non-null DeclaringType", nameof(methodInfo));
38+
39+
}
40+
}
41+
42+
private SerializableMethodInfo(SerializationInfo info, StreamingContext context)
43+
{
44+
System.Type declaringType = info.GetValue<SerializableSystemType>("declaringType")?.GetType();
45+
string fieldName = info.GetString("methodName");
46+
SerializableSystemType[] parameterSystemTypes = info.GetValue<SerializableSystemType[]>("parameterTypesHelper");
47+
48+
System.Type[] parameterTypes = parameterSystemTypes?.Select(x => x.GetType()).ToArray() ?? new System.Type[0];
49+
this._methodInfo = declaringType?.GetMethod(
50+
fieldName,
51+
BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null);
52+
}
53+
54+
public void GetObjectData(SerializationInfo info, StreamingContext context)
55+
{
56+
SerializableSystemType[] parameterSystemTypes =
57+
_methodInfo?.GetParameters()
58+
.Select(x => new SerializableSystemType(x.ParameterType))
59+
.ToArray();
60+
61+
info.AddValueWithType("declaringType", SerializableSystemType.Wrap(_methodInfo?.DeclaringType));
62+
info.AddValue("methodName", _methodInfo?.Name);
63+
info.AddValueWithType("parameterTypesHelper", parameterSystemTypes);
64+
}
65+
66+
public MethodInfo Value => _methodInfo;
67+
68+
private bool Equals(SerializableMethodInfo other)
69+
{
70+
return Equals(_methodInfo, other._methodInfo);
71+
}
72+
73+
public override bool Equals(object obj)
74+
{
75+
if (ReferenceEquals(null, obj)) return false;
76+
if (ReferenceEquals(this, obj)) return true;
77+
if (ReferenceEquals(this._methodInfo, obj)) return true;
78+
if (obj is SerializableMethodInfo) return Equals((SerializableMethodInfo) obj);
79+
return (obj is MethodInfo) && this._methodInfo.Equals(obj);
80+
}
81+
82+
public override int GetHashCode()
83+
{
84+
return _methodInfo.GetHashCode();
85+
}
86+
}
87+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Reflection;
4+
using System.Runtime.Serialization;
5+
6+
namespace NHibernate.Util
7+
{
8+
[Serializable]
9+
internal sealed class SerializablePropertyInfo : ISerializable
10+
{
11+
[NonSerialized]
12+
private readonly PropertyInfo _propertyInfo;
13+
14+
/// <summary>
15+
/// Creates a new instance of <see cref="SerializablePropertyInfo"/> if
16+
/// <paramref name="propertyInfo"/> is not null, otherwise returns <c>null</c>.
17+
/// </summary>
18+
/// <param name="propertyInfo">The <see cref="PropertyInfo"/> being wrapped for serialization.</param>
19+
/// <returns>New instance of <see cref="SerializablePropertyInfo"/> or <c>null</c>.</returns>
20+
public static SerializablePropertyInfo Wrap(PropertyInfo propertyInfo)
21+
{
22+
return propertyInfo == null ? null : new SerializablePropertyInfo(propertyInfo);
23+
}
24+
25+
/// <summary>
26+
/// Creates a new <see cref="SerializablePropertyInfo"/>
27+
/// </summary>
28+
/// <param name="propertyInfo">The <see cref="PropertyInfo"/> being wrapped for serialization.</param>
29+
public SerializablePropertyInfo(PropertyInfo propertyInfo)
30+
{
31+
_propertyInfo = propertyInfo;
32+
if (propertyInfo != null)
33+
{
34+
if (propertyInfo.DeclaringType == null) throw new ArgumentException("PropertyInfo must have non-null DeclaringType", nameof(propertyInfo));
35+
if (propertyInfo.GetIndexParameters().Length > 0) throw new ArgumentException("PropertyInfo not supported with IndexParameters", nameof(propertyInfo));
36+
37+
}
38+
}
39+
40+
private SerializablePropertyInfo(SerializationInfo info, StreamingContext context)
41+
{
42+
System.Type declaringType = info.GetValue<SerializableSystemType>("declaringType")?.GetType();
43+
string propertyName = info.GetString("propertyName");
44+
45+
this._propertyInfo = declaringType?.GetProperty(
46+
propertyName,
47+
BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
48+
}
49+
50+
public void GetObjectData(SerializationInfo info, StreamingContext context)
51+
{
52+
info.AddValueWithType("declaringType", SerializableSystemType.Wrap(_propertyInfo?.DeclaringType));
53+
info.AddValue("propertyName", _propertyInfo?.Name);
54+
}
55+
56+
public PropertyInfo Value => _propertyInfo;
57+
}
58+
}

0 commit comments

Comments
 (0)