diff --git a/build/SkiaSharp.props b/build/SkiaSharp.props
index cc573825cd..31619399f9 100644
--- a/build/SkiaSharp.props
+++ b/build/SkiaSharp.props
@@ -1,7 +1,7 @@
-
-
-
+
+
+
diff --git a/src/Avalonia.Base/Animation/Animation.cs b/src/Avalonia.Base/Animation/Animation.cs
index 6bb06367de..e0883901fd 100644
--- a/src/Avalonia.Base/Animation/Animation.cs
+++ b/src/Avalonia.Base/Animation/Animation.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
@@ -179,14 +180,14 @@ namespace Avalonia.Animation
public KeyFrames Children { get; } = new KeyFrames();
// Store values for the Animator attached properties for IAnimationSetter objects.
- private static readonly Dictionary s_animators = new Dictionary();
+ private static readonly Dictionary Factory)> s_animators = new();
///
/// Gets the value of the Animator attached property for a setter.
///
/// The animation setter.
/// The property animator type.
- public static Type? GetAnimator(IAnimationSetter setter)
+ public static (Type Type, Func Factory)? GetAnimator(IAnimationSetter setter)
{
if (s_animators.TryGetValue(setter, out var type))
{
@@ -200,24 +201,28 @@ namespace Avalonia.Animation
///
/// The animation setter.
/// The property animator value.
- public static void SetAnimator(IAnimationSetter setter, Type value)
+ public static void SetAnimator(IAnimationSetter setter,
+#if NET6_0_OR_GREATER
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.PublicMethods)]
+#endif
+ Type value)
{
- s_animators[setter] = value;
+ s_animators[setter] = (value, () => (IAnimator)Activator.CreateInstance(value)!);
}
- private readonly static List<(Func Condition, Type Animator)> Animators = new List<(Func, Type)>
+ private readonly static List<(Func Condition, Type Animator, Func Factory)> Animators = new()
{
- ( prop => typeof(bool).IsAssignableFrom(prop.PropertyType), typeof(BoolAnimator) ),
- ( prop => typeof(byte).IsAssignableFrom(prop.PropertyType), typeof(ByteAnimator) ),
- ( prop => typeof(Int16).IsAssignableFrom(prop.PropertyType), typeof(Int16Animator) ),
- ( prop => typeof(Int32).IsAssignableFrom(prop.PropertyType), typeof(Int32Animator) ),
- ( prop => typeof(Int64).IsAssignableFrom(prop.PropertyType), typeof(Int64Animator) ),
- ( prop => typeof(UInt16).IsAssignableFrom(prop.PropertyType), typeof(UInt16Animator) ),
- ( prop => typeof(UInt32).IsAssignableFrom(prop.PropertyType), typeof(UInt32Animator) ),
- ( prop => typeof(UInt64).IsAssignableFrom(prop.PropertyType), typeof(UInt64Animator) ),
- ( prop => typeof(float).IsAssignableFrom(prop.PropertyType), typeof(FloatAnimator) ),
- ( prop => typeof(double).IsAssignableFrom(prop.PropertyType), typeof(DoubleAnimator) ),
- ( prop => typeof(decimal).IsAssignableFrom(prop.PropertyType), typeof(DecimalAnimator) ),
+ ( prop => typeof(bool).IsAssignableFrom(prop.PropertyType), typeof(BoolAnimator), () => new BoolAnimator() ),
+ ( prop => typeof(byte).IsAssignableFrom(prop.PropertyType), typeof(ByteAnimator), () => new ByteAnimator() ),
+ ( prop => typeof(Int16).IsAssignableFrom(prop.PropertyType), typeof(Int16Animator), () => new Int16Animator() ),
+ ( prop => typeof(Int32).IsAssignableFrom(prop.PropertyType), typeof(Int32Animator), () => new Int32Animator() ),
+ ( prop => typeof(Int64).IsAssignableFrom(prop.PropertyType), typeof(Int64Animator), () => new Int64Animator() ),
+ ( prop => typeof(UInt16).IsAssignableFrom(prop.PropertyType), typeof(UInt16Animator), () => new UInt16Animator() ),
+ ( prop => typeof(UInt32).IsAssignableFrom(prop.PropertyType), typeof(UInt32Animator), () => new UInt32Animator() ),
+ ( prop => typeof(UInt64).IsAssignableFrom(prop.PropertyType), typeof(UInt64Animator), () => new UInt64Animator() ),
+ ( prop => typeof(float).IsAssignableFrom(prop.PropertyType), typeof(FloatAnimator), () => new FloatAnimator() ),
+ ( prop => typeof(double).IsAssignableFrom(prop.PropertyType), typeof(DoubleAnimator), () => new DoubleAnimator() ),
+ ( prop => typeof(decimal).IsAssignableFrom(prop.PropertyType), typeof(DecimalAnimator), () => new DecimalAnimator() ),
};
///
@@ -232,18 +237,18 @@ namespace Avalonia.Animation
/// The type of the animator to instantiate.
///
public static void RegisterAnimator(Func condition)
- where TAnimator : IAnimator
+ where TAnimator : IAnimator, new()
{
- Animators.Insert(0, (condition, typeof(TAnimator)));
+ Animators.Insert(0, (condition, typeof(TAnimator), () => new TAnimator()));
}
- private static Type? GetAnimatorType(AvaloniaProperty property)
+ private static (Type Type, Func Factory)? GetAnimatorType(AvaloniaProperty property)
{
- foreach (var (condition, type) in Animators)
+ foreach (var (condition, type, factory) in Animators)
{
if (condition(property))
{
- return type;
+ return (type, factory);
}
}
return null;
@@ -251,7 +256,7 @@ namespace Avalonia.Animation
private (IList Animators, IList subscriptions) InterpretKeyframes(Animatable control)
{
- var handlerList = new List<(Type type, AvaloniaProperty property)>();
+ var handlerList = new Dictionary<(Type type, AvaloniaProperty Property), Func>();
var animatorKeyFrames = new List();
var subscriptions = new List();
@@ -271,8 +276,10 @@ namespace Avalonia.Animation
throw new InvalidOperationException($"No animator registered for the property {setter.Property}. Add an animator to the Animation.Animators collection that matches this property to animate it.");
}
- if (!handlerList.Contains((handler, setter.Property)))
- handlerList.Add((handler, setter.Property));
+ var (type, factory) = handler.Value;
+
+ if (!handlerList.ContainsKey((type, setter.Property)))
+ handlerList[(type, setter.Property)] = factory;
var cue = keyframe.Cue;
@@ -281,7 +288,7 @@ namespace Avalonia.Animation
cue = new Cue(keyframe.KeyTime.TotalSeconds / Duration.TotalSeconds);
}
- var newKF = new AnimatorKeyFrame(handler, cue, keyframe.KeySpline);
+ var newKF = new AnimatorKeyFrame(type, factory, cue, keyframe.KeySpline);
subscriptions.Add(newKF.BindSetter(setter, control));
@@ -291,10 +298,10 @@ namespace Avalonia.Animation
var newAnimatorInstances = new List();
- foreach (var (handlerType, property) in handlerList)
+ foreach (var handler in handlerList)
{
- var newInstance = (IAnimator)Activator.CreateInstance(handlerType)!;
- newInstance.Property = property;
+ var newInstance = handler.Value();
+ newInstance.Property = handler.Key.Property;
newAnimatorInstances.Add(newInstance);
}
diff --git a/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs b/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs
index 8af31f2948..0356723f00 100644
--- a/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs
+++ b/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs
@@ -20,22 +20,25 @@ namespace Avalonia.Animation
}
- public AnimatorKeyFrame(Type? animatorType, Cue cue)
+ public AnimatorKeyFrame(Type? animatorType, Func? animatorFactory, Cue cue)
{
AnimatorType = animatorType;
+ AnimatorFactory = animatorFactory;
Cue = cue;
KeySpline = null;
}
- public AnimatorKeyFrame(Type? animatorType, Cue cue, KeySpline? keySpline)
+ public AnimatorKeyFrame(Type? animatorType, Func? animatorFactory, Cue cue, KeySpline? keySpline)
{
AnimatorType = animatorType;
+ AnimatorFactory = animatorFactory;
Cue = cue;
KeySpline = keySpline;
}
internal bool isNeutral;
public Type? AnimatorType { get; }
+ public Func? AnimatorFactory { get; }
public Cue Cue { get; }
public KeySpline? KeySpline { get; }
public AvaloniaProperty? Property { get; private set; }
diff --git a/src/Avalonia.Base/Animation/Animators/Animator`1.cs b/src/Avalonia.Base/Animation/Animators/Animator`1.cs
index 248ca61c1d..8765cfb4c9 100644
--- a/src/Avalonia.Base/Animation/Animators/Animator`1.cs
+++ b/src/Avalonia.Base/Animation/Animators/Animator`1.cs
@@ -171,12 +171,12 @@ namespace Avalonia.Animation.Animators
{
if (!hasStartKey)
{
- _convertedKeyframes.Insert(0, new AnimatorKeyFrame(null, new Cue(0.0d)) { Value = default(T), isNeutral = true });
+ _convertedKeyframes.Insert(0, new AnimatorKeyFrame(null, null, new Cue(0.0d)) { Value = default(T), isNeutral = true });
}
if (!hasEndKey)
{
- _convertedKeyframes.Add(new AnimatorKeyFrame(null, new Cue(1.0d)) { Value = default(T), isNeutral = true });
+ _convertedKeyframes.Add(new AnimatorKeyFrame(null, null, new Cue(1.0d)) { Value = default(T), isNeutral = true });
}
}
}
diff --git a/src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs b/src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs
index 5f22254fb5..07c147ef6d 100644
--- a/src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs
+++ b/src/Avalonia.Base/Animation/Animators/BaseBrushAnimator.cs
@@ -17,8 +17,7 @@ namespace Avalonia.Animation.Animators
///
public class BaseBrushAnimator : Animator
{
- private static readonly List<(Func Match, Type AnimatorType)> _brushAnimators =
- new List<(Func Match, Type AnimatorType)>();
+ private static readonly List<(Func Match, Type AnimatorType, Func AnimatorFactory)> _brushAnimators = new();
///
/// Register an that handles a specific
@@ -34,7 +33,7 @@ namespace Avalonia.Animation.Animators
public static void RegisterBrushAnimator(Func condition)
where TAnimator : IAnimator, new()
{
- _brushAnimators.Insert(0, (condition, typeof(TAnimator)));
+ _brushAnimators.Insert(0, (condition, typeof(TAnimator), () => new TAnimator()));
}
///
@@ -85,14 +84,14 @@ namespace Avalonia.Animation.Animators
{
if (keyframe.Value is ISolidColorBrush solidColorBrush)
{
- gradientAnimator.Add(new AnimatorKeyFrame(typeof(GradientBrushAnimator), keyframe.Cue, keyframe.KeySpline)
+ gradientAnimator.Add(new AnimatorKeyFrame(typeof(GradientBrushAnimator), () => new GradientBrushAnimator(), keyframe.Cue, keyframe.KeySpline)
{
Value = GradientBrushAnimator.ConvertSolidColorBrushToGradient(firstGradient, solidColorBrush)
});
}
else if (keyframe.Value is IGradientBrush)
{
- gradientAnimator.Add(new AnimatorKeyFrame(typeof(GradientBrushAnimator), keyframe.Cue, keyframe.KeySpline)
+ gradientAnimator.Add(new AnimatorKeyFrame(typeof(GradientBrushAnimator), () => new GradientBrushAnimator(), keyframe.Cue, keyframe.KeySpline)
{
Value = keyframe.Value
});
@@ -117,7 +116,7 @@ namespace Avalonia.Animation.Animators
{
if (keyframe.Value is ISolidColorBrush)
{
- solidColorBrushAnimator.Add(new AnimatorKeyFrame(typeof(ISolidColorBrushAnimator), keyframe.Cue, keyframe.KeySpline)
+ solidColorBrushAnimator.Add(new AnimatorKeyFrame(typeof(ISolidColorBrushAnimator), () => new ISolidColorBrushAnimator(), keyframe.Cue, keyframe.KeySpline)
{
Value = keyframe.Value
});
@@ -137,18 +136,18 @@ namespace Avalonia.Animation.Animators
{
if (_brushAnimators.Count > 0 && this[0].Value?.GetType() is Type firstKeyType)
{
- foreach (var (match, animatorType) in _brushAnimators)
+ foreach (var (match, animatorType, animatorFactory) in _brushAnimators)
{
if (!match(firstKeyType))
continue;
- animator = (IAnimator?)Activator.CreateInstance(animatorType);
+ animator = animatorFactory();
if (animator != null)
{
animator.Property = Property;
foreach (var keyframe in this)
{
- animator.Add(new AnimatorKeyFrame(animatorType, keyframe.Cue, keyframe.KeySpline)
+ animator.Add(new AnimatorKeyFrame(animatorType, animatorFactory, keyframe.Cue, keyframe.KeySpline)
{
Value = keyframe.Value
});
diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj
index 15feed388b..d091b9072d 100644
--- a/src/Avalonia.Base/Avalonia.Base.csproj
+++ b/src/Avalonia.Base/Avalonia.Base.csproj
@@ -6,6 +6,7 @@
True
true
$(BaseIntermediateOutputPath)\GeneratedFiles
+ true