Browse Source

Avoid boxing in EffectiveValue<T>.SetAndRaise.

Added `IValueEntry<T>` interface back in and use that if present to get the value from the entry.
pull/8600/head
Steven Kirk 3 years ago
parent
commit
a9f12cbb43
  1. 11
      src/Avalonia.Base/PropertyStore/BindingEntryBase.cs
  2. 11
      src/Avalonia.Base/PropertyStore/EffectiveValue`1.cs
  3. 16
      src/Avalonia.Base/PropertyStore/IValueEntry`1.cs
  4. 3
      src/Avalonia.Base/PropertyStore/ImmediateValueEntry.cs

11
src/Avalonia.Base/PropertyStore/BindingEntryBase.cs

@ -1,12 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reactive.Disposables;
using Avalonia.Data;
namespace Avalonia.PropertyStore
{
internal abstract class BindingEntryBase<TValue, TSource> : IValueEntry,
internal abstract class BindingEntryBase<TValue, TSource> : IValueEntry<TValue>,
IObserver<TSource>,
IObserver<BindingValue<TSource>>,
IDisposable
@ -58,6 +57,14 @@ namespace Avalonia.PropertyStore
BindingCompleted();
}
public TValue GetValue()
{
Start(produceValue: false);
if (!_hasValue)
throw new AvaloniaInternalException("The binding entry has no value.");
return _value!;
}
public void Start() => Start(true);
public void OnCompleted() => BindingCompleted();

11
src/Avalonia.Base/PropertyStore/EffectiveValue`1.cs

@ -55,7 +55,8 @@ namespace Avalonia.PropertyStore
{
Debug.Assert(priority != BindingPriority.LocalValue);
UpdateValueEntry(value, priority);
SetAndRaiseCore(owner, (StyledPropertyBase<T>)value.Property, (T)value.GetValue()!, priority);
SetAndRaiseCore(owner, (StyledPropertyBase<T>)value.Property, GetValue(value), priority);
}
public void SetLocalValueAndRaise(
@ -144,6 +145,14 @@ namespace Avalonia.PropertyStore
protected override object? GetBoxedValue() => Value;
private static T GetValue(IValueEntry entry)
{
if (entry is IValueEntry<T> typed)
return typed.GetValue();
else
return (T)entry.GetValue()!;
}
private void SetAndRaiseCore(
ValueStore owner,
StyledPropertyBase<T> property,

16
src/Avalonia.Base/PropertyStore/IValueEntry`1.cs

@ -0,0 +1,16 @@
namespace Avalonia.PropertyStore
{
/// <summary>
/// Represents a typed value entry in a <see cref="ValueFrame"/>.
/// </summary>
internal interface IValueEntry<T> : IValueEntry
{
/// <summary>
/// Gets the value associated with the entry.
/// </summary>
/// <exception cref="AvaloniaInternalException">
/// The entry has no value.
/// </exception>
new T GetValue();
}
}

3
src/Avalonia.Base/PropertyStore/ImmediateValueEntry.cs

@ -2,7 +2,7 @@
namespace Avalonia.PropertyStore
{
internal class ImmediateValueEntry<T> : IValueEntry, IDisposable
internal class ImmediateValueEntry<T> : IValueEntry<T>, IDisposable
{
private readonly ImmediateValueFrame _owner;
private readonly T _value;
@ -26,5 +26,6 @@ namespace Avalonia.PropertyStore
public void Dispose() => _owner.OnEntryDisposed(this);
object? IValueEntry.GetValue() => _value;
T IValueEntry<T>.GetValue() => _value;
}
}

Loading…
Cancel
Save