mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-25 22:18:34 +01:00
added a CopyConstructor attribute to CopyExtensions
This commit is contained in:
parent
f68e55ebfd
commit
500025090f
2 changed files with 27 additions and 9 deletions
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace MLEM.Data {
|
namespace MLEM.Data {
|
||||||
|
@ -11,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.
|
/// Note that, for this to work correctly, <typeparamref name="T"/> needs to contain a parameterless constructor or a constructor with the <see cref="CopyConstructorAttribute"/>.
|
||||||
/// </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>
|
||||||
|
@ -26,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.
|
/// Note that, for this to work correctly, <typeparamref name="T"/> needs to contain a parameterless constructor or a constructor with the <see cref="CopyConstructorAttribute"/>.
|
||||||
/// </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>
|
||||||
|
@ -56,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.
|
/// 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"/>.
|
||||||
/// </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>
|
||||||
|
@ -84,11 +85,23 @@ namespace MLEM.Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static object Construct(Type t, BindingFlags flags) {
|
private static object Construct(Type t, BindingFlags flags) {
|
||||||
var constructor = t.GetConstructor(flags, null, Type.EmptyTypes, null);
|
// find a contructor with the correct attribute
|
||||||
|
var constructor = t.GetConstructors().FirstOrDefault(c => c.GetCustomAttribute<CopyConstructorAttribute>() != null);
|
||||||
|
// fall back to a parameterless constructor
|
||||||
if (constructor == null)
|
if (constructor == null)
|
||||||
throw new NullReferenceException($"Type {t} does not have a parameterless constructor with the required visibility");
|
constructor = t.GetConstructor(flags, null, Type.EmptyTypes, null);
|
||||||
return constructor.Invoke(null);
|
if (constructor == null)
|
||||||
|
throw new NullReferenceException($"Type {t} does not have a parameterless constructor with the required visibility or a constructor with the CopyConstructorAttribute");
|
||||||
|
return constructor.Invoke(new object[constructor.GetParameters().Length]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An attribute that, when added to a constructor, will make that constructor the one used by <see cref="CopyExtensions.Copy{T}"/>, <see cref="CopyExtensions.DeepCopy{T}"/> and <see cref="CopyExtensions.DeepCopyInto{T}"/>.
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Constructor)]
|
||||||
|
public class CopyConstructorAttribute : Attribute {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -89,11 +89,11 @@ namespace Sandbox {
|
||||||
panel.SetData("TestKey", new Vector2(10, 2));
|
panel.SetData("TestKey", new Vector2(10, 2));
|
||||||
//Console.WriteLine(panel.GetData<Vector2>("TestKey"));
|
//Console.WriteLine(panel.GetData<Vector2>("TestKey"));
|
||||||
|
|
||||||
var obj = new Test {
|
var obj = new Test(Vector2.One, "test") {
|
||||||
Vec = new Vector2(10, 20),
|
Vec = new Vector2(10, 20),
|
||||||
Point = new Point(20, 30),
|
Point = new Point(20, 30),
|
||||||
Dir = Direction2.Left,
|
Dir = Direction2.Left,
|
||||||
OtherTest = new Test {
|
OtherTest = new Test(Vector2.One, "other") {
|
||||||
Vec = new Vector2(70, 30),
|
Vec = new Vector2(70, 30),
|
||||||
Dir = Direction2.Right
|
Dir = Direction2.Right
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ namespace Sandbox {
|
||||||
var copy = obj.DeepCopy();
|
var copy = obj.DeepCopy();
|
||||||
Console.WriteLine(copy);
|
Console.WriteLine(copy);
|
||||||
|
|
||||||
var intoCopy = new Test {OtherTest = new Test()};
|
var intoCopy = new Test(Vector2.One, "test") {OtherTest = new Test(Vector2.One, "other")};
|
||||||
obj.DeepCopyInto(intoCopy);
|
obj.DeepCopyInto(intoCopy);
|
||||||
Console.WriteLine(intoCopy);
|
Console.WriteLine(intoCopy);
|
||||||
|
|
||||||
|
@ -234,6 +234,11 @@ namespace Sandbox {
|
||||||
public Direction2 Dir { get; set; }
|
public Direction2 Dir { get; set; }
|
||||||
public Test OtherTest;
|
public Test OtherTest;
|
||||||
|
|
||||||
|
[CopyConstructor]
|
||||||
|
public Test(Vector2 test, string test2) {
|
||||||
|
Console.WriteLine("Constructed with " + test + ", " + test2);
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
return $"{this.GetHashCode()}: {nameof(this.Vec)}: {this.Vec}, {nameof(this.Point)}: {this.Point}, {nameof(this.OtherTest)}: {this.OtherTest}, {nameof(this.Dir)}: {this.Dir}";
|
return $"{this.GetHashCode()}: {nameof(this.Vec)}: {this.Vec}, {nameof(this.Point)}: {this.Point}, {nameof(this.OtherTest)}: {this.OtherTest}, {nameof(this.Dir)}: {this.Dir}";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue