1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-06-16 10:44:32 +02:00

made CopyExtensions be able to fall back to a generic constructor if none is found

This commit is contained in:
Ell 2020-11-01 15:36:56 +01:00
parent 62f9b86c1d
commit 75d8a556eb

View file

@ -12,7 +12,7 @@ namespace MLEM.Data {
/// <summary> /// <summary>
/// Creates a shallow copy of the object and returns it. /// Creates a shallow copy of the object and returns it.
/// Note that, for this to work correctly, <typeparamref name="T"/> needs to contain a parameterless constructor or a constructor with the <see cref="CopyConstructorAttribute"/>. /// Object creation occurs using a constructor with the <see cref="CopyConstructorAttribute"/> or, if none is present, the first constructor with the correct <see cref="BindingFlags"/>.
/// </summary> /// </summary>
/// <param name="obj">The object to create a shallow copy of</param> /// <param name="obj">The object to create a shallow copy of</param>
/// <param name="flags">The binding flags for field searching</param> /// <param name="flags">The binding flags for field searching</param>
@ -27,7 +27,7 @@ namespace MLEM.Data {
/// <summary> /// <summary>
/// Creates a deep copy of the object and returns it. /// Creates a deep copy of the object and returns it.
/// Note that, for this to work correctly, <typeparamref name="T"/> needs to contain a parameterless constructor or a constructor with the <see cref="CopyConstructorAttribute"/>. /// Object creation occurs using a constructor with the <see cref="CopyConstructorAttribute"/> or, if none is present, the first constructor with the correct <see cref="BindingFlags"/>.
/// </summary> /// </summary>
/// <param name="obj">The object to create a deep copy of</param> /// <param name="obj">The object to create a deep copy of</param>
/// <param name="flags">The binding flags for field searching</param> /// <param name="flags">The binding flags for field searching</param>
@ -57,7 +57,7 @@ namespace MLEM.Data {
/// <summary> /// <summary>
/// Copies the given object <paramref name="obj"/> into the given object <paramref name="otherObj"/> in a deep manner. /// Copies the given object <paramref name="obj"/> into the given object <paramref name="otherObj"/> in a deep manner.
/// Note that, for this to work correctly, each type that should be constructed below the topmost level needs to contanin a parameterless constructor or a constructor with the <see cref="CopyConstructorAttribute"/>. /// Object creation occurs using a constructor with the <see cref="CopyConstructorAttribute"/> or, if none is present, the first constructor with the correct <see cref="BindingFlags"/>.
/// </summary> /// </summary>
/// <param name="obj">The object to create a deep copy of</param> /// <param name="obj">The object to create a deep copy of</param>
/// <param name="otherObj">The object to copy into</param> /// <param name="otherObj">The object to copy into</param>
@ -85,13 +85,17 @@ namespace MLEM.Data {
} }
private static object Construct(Type t, BindingFlags flags) { private static object Construct(Type t, BindingFlags flags) {
var constructors = t.GetConstructors(flags);
// find a contructor with the correct attribute // find a contructor with the correct attribute
var constructor = t.GetConstructors(flags).FirstOrDefault(c => c.GetCustomAttribute<CopyConstructorAttribute>() != null); var constructor = constructors.FirstOrDefault(c => c.GetCustomAttribute<CopyConstructorAttribute>() != null);
// fall back to a parameterless constructor // find a parameterless construcotr
if (constructor == null) if (constructor == null)
constructor = t.GetConstructor(flags, null, Type.EmptyTypes, null); constructor = t.GetConstructor(flags, null, Type.EmptyTypes, null);
// fall back to the first constructor
if (constructor == null) if (constructor == null)
throw new NullReferenceException($"Type {t} does not have a parameterless constructor or a constructor with the CopyConstructorAttribute with the required visibility"); constructor = constructors.FirstOrDefault();
if (constructor == null)
throw new NullReferenceException($"Type {t} does not have a constructor with the required visibility");
return constructor.Invoke(new object[constructor.GetParameters().Length]); return constructor.Invoke(new object[constructor.GetParameters().Length]);
} }