Skip to content

Commit 629340b

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 73868e1 commit 629340b

8 files changed

+475
-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+
}

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: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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, IEquatable<SerializableConstructorInfo>
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").GetSystemType();
42+
SerializableSystemType[] parameterSystemTypes = info.GetValue<SerializableSystemType[]>("parameterTypesHelper");
43+
44+
System.Type[] parameterTypes = parameterSystemTypes?.Select(x => x.GetSystemType()).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+
public bool Equals(SerializableConstructorInfo other)
65+
{
66+
return other != null && 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+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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, IEquatable<SerializableFieldInfo>
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").GetSystemType();
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+
public bool Equals(SerializableFieldInfo other)
58+
{
59+
return other != null && Equals(_fieldInfo, other._fieldInfo);
60+
}
61+
62+
public override bool Equals(object obj)
63+
{
64+
if (ReferenceEquals(null, obj)) return false;
65+
if (ReferenceEquals(this, obj)) return true;
66+
return obj is SerializableFieldInfo && Equals((SerializableFieldInfo) obj);
67+
}
68+
69+
public override int GetHashCode()
70+
{
71+
return (_fieldInfo != null ? _fieldInfo.GetHashCode() : 0);
72+
}
73+
}
74+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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 SerializableMethodInfo : ISerializable, IEquatable<SerializableMethodInfo>
11+
{
12+
[NonSerialized]
13+
private readonly MethodInfo _methodInfo;
14+
15+
/// <summary>
16+
/// Creates a new instance of <see cref="SerializableMethodInfo"/> if
17+
/// <paramref name="methodInfo"/> is not null, otherwise returns <c>null</c>.
18+
/// </summary>
19+
/// <param name="methodInfo">The <see cref="MethodInfo"/> being wrapped for serialization.</param>
20+
/// <returns>New instance of <see cref="SerializableMethodInfo"/> or <c>null</c>.</returns>
21+
public static SerializableMethodInfo Wrap(MethodInfo methodInfo)
22+
{
23+
return methodInfo == null ? null : new SerializableMethodInfo(methodInfo);
24+
}
25+
26+
/// <summary>
27+
/// Creates a new <see cref="SerializableMethodInfo"/>
28+
/// </summary>
29+
/// <param name="methodInfo">The <see cref="MethodInfo"/> being wrapped for serialization.</param>
30+
private SerializableMethodInfo(MethodInfo methodInfo)
31+
{
32+
_methodInfo = methodInfo ?? throw new ArgumentNullException(nameof(methodInfo));
33+
if (methodInfo.IsStatic) throw new ArgumentException("Only for instance fields", nameof(methodInfo));
34+
if (methodInfo.DeclaringType == null) throw new ArgumentException("MethodInfo must have non-null DeclaringType", nameof(methodInfo));
35+
}
36+
37+
private SerializableMethodInfo(SerializationInfo info, StreamingContext context)
38+
{
39+
System.Type declaringType = info.GetValue<SerializableSystemType>("declaringType").GetSystemType();
40+
string methodName = info.GetString("methodName");
41+
SerializableSystemType[] parameterSystemTypes = info.GetValue<SerializableSystemType[]>("parameterTypesHelper");
42+
43+
System.Type[] parameterTypes = parameterSystemTypes?.Select(x => x.GetSystemType()).ToArray() ?? new System.Type[0];
44+
_methodInfo = declaringType.GetMethod(
45+
methodName,
46+
BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null);
47+
48+
if (_methodInfo == null) throw new MissingMethodException(declaringType.FullName, methodName);
49+
}
50+
51+
[SecurityCritical]
52+
public void GetObjectData(SerializationInfo info, StreamingContext context)
53+
{
54+
SerializableSystemType[] parameterSystemTypes =
55+
_methodInfo.GetParameters()
56+
.Select(x => SerializableSystemType.Wrap(x.ParameterType))
57+
.ToArray();
58+
59+
info.AddValue("declaringType", SerializableSystemType.Wrap(_methodInfo.DeclaringType));
60+
info.AddValue("methodName", _methodInfo.Name);
61+
info.AddValue("parameterTypesHelper", parameterSystemTypes);
62+
}
63+
64+
public MethodInfo Value => _methodInfo;
65+
66+
public bool Equals(SerializableMethodInfo other)
67+
{
68+
return other != null && Equals(_methodInfo, other._methodInfo);
69+
}
70+
}
71+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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 SerializablePropertyInfo : ISerializable, IEquatable<SerializablePropertyInfo>
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+
private SerializablePropertyInfo(PropertyInfo propertyInfo)
30+
{
31+
_propertyInfo = propertyInfo ?? throw new ArgumentNullException(nameof(propertyInfo));
32+
if (propertyInfo.DeclaringType == null) throw new ArgumentException("PropertyInfo must have non-null DeclaringType", nameof(propertyInfo));
33+
if (propertyInfo.GetIndexParameters().Length > 0) throw new ArgumentException("PropertyInfo not supported with IndexParameters", nameof(propertyInfo));
34+
}
35+
36+
private SerializablePropertyInfo(SerializationInfo info, StreamingContext context)
37+
{
38+
System.Type declaringType = info.GetValue<SerializableSystemType>("declaringType").GetSystemType();
39+
string propertyName = info.GetString("propertyName");
40+
41+
_propertyInfo = declaringType.GetProperty(
42+
propertyName,
43+
BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
44+
45+
if (_propertyInfo == null) throw new MissingMethodException(declaringType.FullName, propertyName);
46+
}
47+
48+
[SecurityCritical]
49+
public void GetObjectData(SerializationInfo info, StreamingContext context)
50+
{
51+
info.AddValue("declaringType", SerializableSystemType.Wrap(_propertyInfo.DeclaringType));
52+
info.AddValue("propertyName", _propertyInfo.Name);
53+
}
54+
55+
public PropertyInfo Value => _propertyInfo;
56+
57+
public bool Equals(SerializablePropertyInfo other)
58+
{
59+
return other != null && Equals(_propertyInfo, other._propertyInfo);
60+
}
61+
62+
public override bool Equals(object obj)
63+
{
64+
if (ReferenceEquals(null, obj)) return false;
65+
if (ReferenceEquals(this, obj)) return true;
66+
return obj is SerializablePropertyInfo && Equals((SerializablePropertyInfo) obj);
67+
}
68+
69+
public override int GetHashCode()
70+
{
71+
return (_propertyInfo != null ? _propertyInfo.GetHashCode() : 0);
72+
}
73+
}
74+
}

0 commit comments

Comments
 (0)