2025-05-09 15:40:34 +08:00

83 lines
3.4 KiB
C#

// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
using System;
namespace Animancer
{
/// <summary>An object that can be copied.</summary>
/// https://kybernetik.com.au/animancer/api/Animancer/ICopyable_1
public interface ICopyable<in T>
{
/************************************************************************************************************************/
/// <summary>Copies the contents of `copyFrom` into this object, replacing its previous contents.</summary>
void CopyFrom(T copyFrom, CloneContext context);
/************************************************************************************************************************/
}
/// <summary>Extension methods for <see cref="ICopyable{T}"/>.</summary>
/// https://kybernetik.com.au/animancer/api/Animancer/CopyableExtensions
public static partial class CopyableExtensions
{
/************************************************************************************************************************/
/// <summary>
/// Calls <see cref="ICopyable{T}.CopyFrom"/>
/// using a <see cref="CloneContext"/> from the <see cref="CloneContext.Pool"/>.
/// </summary>
public static void CopyFrom<T>(this T copyTo, T copyFrom)
where T : ICopyable<T>
{
var context = CloneContext.Pool.Instance.Acquire();
copyTo.CopyFrom(copyFrom, context);
CloneContext.Pool.Instance.Release(context);
}
/************************************************************************************************************************/
/// <summary>
/// Creates a new <typeparamref name="T"/> and calls <see cref="ICopyable{T}.CopyFrom"/>.
/// </summary>
public static T CopyableClone<T>(this T original, CloneContext context)
where T : ICopyable<T>
{
if (original == null)
return default;
var clone = (T)Activator.CreateInstance(original.GetType());
clone.CopyFrom(original, context);
return clone;
}
/// <summary>
/// Creates a new <typeparamref name="T"/> and calls <see cref="ICopyable{T}.CopyFrom"/>
/// using a <see cref="CloneContext"/> from the <see cref="CloneContext.Pool"/>.
/// </summary>
public static T CopyableClone<T>(this T original)
where T : ICopyable<T>
{
var context = CloneContext.Pool.Instance.Acquire();
var clone = original.CopyableClone(context);
CloneContext.Pool.Instance.Release(context);
return clone;
}
/************************************************************************************************************************/
/// <summary>Calls <see cref="ICopyable{T}.CopyFrom"/> using the appropriate type.</summary>
public static void CopyFromBase<TChild, TBase>(this TChild copyTo, TBase copyFrom, CloneContext context)
where TChild : ICopyable<TChild>, ICopyable<TBase>
where TBase : ICopyable<TBase>
{
if (copyFrom is TChild copyFromChild)
copyTo.CopyFrom(copyFromChild, context);
else
copyTo.CopyFrom(copyFrom, context);
}
/************************************************************************************************************************/
}
}