Browse Source

Merge branch 'RXUI8' of https://github.com/jkoritzinsky/Avalonia into RXUI8

pull/1086/head
Jeremy Koritzinsky 9 years ago
parent
commit
ff8a6e4251
  1. 5
      src/Avalonia.Base/Utilities/WeakObservable.cs
  2. 24
      src/Avalonia.Base/Utilities/WeakSubscriptionManager.cs
  3. 8
      src/Markup/Avalonia.Markup/Data/IndexerNode.cs
  4. 10
      src/Markup/Avalonia.Markup/Data/Plugins/AvaloniaPropertyAccessorPlugin.cs
  5. 7
      src/Markup/Avalonia.Markup/Data/Plugins/IPropertyAccessorPlugin.cs
  6. 6
      src/Markup/Avalonia.Markup/Data/Plugins/InpcPropertyAccessorPlugin.cs
  7. 2
      src/Markup/Avalonia.Markup/Data/PropertyAccessorNode.cs
  8. 12
      tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_AvaloniaProperty.cs

5
src/Avalonia.Base/Utilities/WeakObservable.cs

@ -16,12 +16,13 @@ namespace Avalonia.Utilities
/// Converts a .NET event conforming to the standard .NET event pattern into an observable /// Converts a .NET event conforming to the standard .NET event pattern into an observable
/// sequence, subscribing weakly. /// sequence, subscribing weakly.
/// </summary> /// </summary>
/// <typeparam name="TTarget">The type of target.</typeparam>
/// <typeparam name="TEventArgs">The type of the event args.</typeparam> /// <typeparam name="TEventArgs">The type of the event args.</typeparam>
/// <param name="target">Object instance that exposes the event to convert.</param> /// <param name="target">Object instance that exposes the event to convert.</param>
/// <param name="eventName">Name of the event to convert.</param> /// <param name="eventName">Name of the event to convert.</param>
/// <returns></returns> /// <returns></returns>
public static IObservable<EventPattern<object, TEventArgs>> FromEventPattern<TEventArgs>( public static IObservable<EventPattern<object, TEventArgs>> FromEventPattern<TTarget, TEventArgs>(
object target, TTarget target,
string eventName) string eventName)
where TEventArgs : EventArgs where TEventArgs : EventArgs
{ {

24
src/Avalonia.Base/Utilities/WeakSubscriptionManager.cs

@ -17,22 +17,23 @@ namespace Avalonia.Utilities
/// <summary> /// <summary>
/// Subscribes to an event on an object using a weak subscription. /// Subscribes to an event on an object using a weak subscription.
/// </summary> /// </summary>
/// <typeparam name="T">The type of the event arguments.</typeparam> /// <typeparam name="TTarget">The type of the target.</typeparam>
/// <typeparam name="TEventArgs">The type of the event arguments.</typeparam>
/// <param name="target">The event source.</param> /// <param name="target">The event source.</param>
/// <param name="eventName">The name of the event.</param> /// <param name="eventName">The name of the event.</param>
/// <param name="subscriber">The subscriber.</param> /// <param name="subscriber">The subscriber.</param>
public static void Subscribe<T>(object target, string eventName, IWeakSubscriber<T> subscriber) public static void Subscribe<TTarget, TEventArgs>(TTarget target, string eventName, IWeakSubscriber<TEventArgs> subscriber)
where T : EventArgs where TEventArgs : EventArgs
{ {
var dic = SubscriptionTypeStorage<T>.Subscribers.GetOrCreateValue(target); var dic = SubscriptionTypeStorage<TEventArgs>.Subscribers.GetOrCreateValue(target);
Subscription<T> sub; Subscription<TEventArgs> sub;
if (!dic.TryGetValue(eventName, out sub)) if (!dic.TryGetValue(eventName, out sub))
{ {
dic[eventName] = sub = new Subscription<T>(dic, target, eventName); dic[eventName] = sub = new Subscription<TEventArgs>(dic, typeof(TTarget), target, eventName);
} }
sub.Add(new WeakReference<IWeakSubscriber<T>>(subscriber)); sub.Add(new WeakReference<IWeakSubscriber<TEventArgs>>(subscriber));
} }
/// <summary> /// <summary>
@ -84,19 +85,18 @@ namespace Avalonia.Utilities
private WeakReference<IWeakSubscriber<T>>[] _data = new WeakReference<IWeakSubscriber<T>>[16]; private WeakReference<IWeakSubscriber<T>>[] _data = new WeakReference<IWeakSubscriber<T>>[16];
private int _count = 0; private int _count = 0;
public Subscription(SubscriptionDic<T> sdic, object target, string eventName) public Subscription(SubscriptionDic<T> sdic, Type targetType, object target, string eventName)
{ {
_sdic = sdic; _sdic = sdic;
_target = target; _target = target;
_eventName = eventName; _eventName = eventName;
var t = target.GetType();
Dictionary<string, EventInfo> evDic; Dictionary<string, EventInfo> evDic;
if (!Accessors.TryGetValue(t, out evDic)) if (!Accessors.TryGetValue(targetType, out evDic))
Accessors[t] = evDic = new Dictionary<string, EventInfo>(); Accessors[targetType] = evDic = new Dictionary<string, EventInfo>();
if (!evDic.TryGetValue(eventName, out _info)) if (!evDic.TryGetValue(eventName, out _info))
{ {
var ev = t.GetRuntimeEvents().FirstOrDefault(x => x.Name == eventName); var ev = targetType.GetRuntimeEvents().FirstOrDefault(x => x.Name == eventName);
if (ev == null) if (ev == null)
{ {

8
src/Markup/Avalonia.Markup/Data/IndexerNode.cs

@ -33,8 +33,8 @@ namespace Avalonia.Markup.Data
if (incc != null) if (incc != null)
{ {
inputs.Add(WeakObservable.FromEventPattern<NotifyCollectionChangedEventArgs>( inputs.Add(WeakObservable.FromEventPattern<INotifyCollectionChanged, NotifyCollectionChangedEventArgs>(
target, incc,
nameof(incc.CollectionChanged)) nameof(incc.CollectionChanged))
.Where(x => ShouldUpdate(x.Sender, x.EventArgs)) .Where(x => ShouldUpdate(x.Sender, x.EventArgs))
.Select(_ => GetValue(target))); .Select(_ => GetValue(target)));
@ -42,8 +42,8 @@ namespace Avalonia.Markup.Data
if (inpc != null) if (inpc != null)
{ {
inputs.Add(WeakObservable.FromEventPattern<PropertyChangedEventArgs>( inputs.Add(WeakObservable.FromEventPattern<INotifyPropertyChanged, PropertyChangedEventArgs>(
target, inpc,
nameof(inpc.PropertyChanged)) nameof(inpc.PropertyChanged))
.Where(x => ShouldUpdate(x.Sender, x.EventArgs)) .Where(x => ShouldUpdate(x.Sender, x.EventArgs))
.Select(_ => GetValue(target))); .Select(_ => GetValue(target)));

10
src/Markup/Avalonia.Markup/Data/Plugins/AvaloniaPropertyAccessorPlugin.cs

@ -13,7 +13,15 @@ namespace Avalonia.Markup.Data.Plugins
public class AvaloniaPropertyAccessorPlugin : IPropertyAccessorPlugin public class AvaloniaPropertyAccessorPlugin : IPropertyAccessorPlugin
{ {
/// <inheritdoc/> /// <inheritdoc/>
public bool Match(WeakReference reference) => reference.Target is AvaloniaObject; public bool Match(object obj, string propertyName)
{
if (obj is AvaloniaObject a)
{
return AvaloniaPropertyRegistry.Instance.FindRegistered(a, propertyName) != null;
}
return false;
}
/// <summary> /// <summary>
/// Starts monitoring the value of a property on an object. /// Starts monitoring the value of a property on an object.

7
src/Markup/Avalonia.Markup/Data/Plugins/IPropertyAccessorPlugin.cs

@ -14,9 +14,10 @@ namespace Avalonia.Markup.Data.Plugins
/// <summary> /// <summary>
/// Checks whether this plugin can handle accessing the properties of the specified object. /// Checks whether this plugin can handle accessing the properties of the specified object.
/// </summary> /// </summary>
/// <param name="reference">A weak reference to the object.</param> /// <param name="obj">The object.</param>
/// <returns>True if the plugin can handle the object; otherwise false.</returns> /// <param name="propertyName">The property name.</param>
bool Match(WeakReference reference); /// <returns>True if the plugin can handle the property on the object; otherwise false.</returns>
bool Match(object obj, string propertyName);
/// <summary> /// <summary>
/// Starts monitoring the value of a property on an object. /// Starts monitoring the value of a property on an object.

6
src/Markup/Avalonia.Markup/Data/Plugins/InpcPropertyAccessorPlugin.cs

@ -19,7 +19,7 @@ namespace Avalonia.Markup.Data.Plugins
public class InpcPropertyAccessorPlugin : IPropertyAccessorPlugin public class InpcPropertyAccessorPlugin : IPropertyAccessorPlugin
{ {
/// <inheritdoc/> /// <inheritdoc/>
public bool Match(WeakReference reference) => true; public bool Match(object obj, string propertyName) => true;
/// <summary> /// <summary>
/// Starts monitoring the value of a property on an object. /// Starts monitoring the value of a property on an object.
@ -36,7 +36,7 @@ namespace Avalonia.Markup.Data.Plugins
Contract.Requires<ArgumentNullException>(propertyName != null); Contract.Requires<ArgumentNullException>(propertyName != null);
var instance = reference.Target; var instance = reference.Target;
var p = instance.GetType().GetRuntimeProperties().FirstOrDefault(_ => _.Name == propertyName); var p = instance.GetType().GetRuntimeProperties().FirstOrDefault(x => x.Name == propertyName);
if (p != null) if (p != null)
{ {
@ -138,7 +138,7 @@ namespace Avalonia.Markup.Data.Plugins
if (inpc != null) if (inpc != null)
{ {
WeakSubscriptionManager.Subscribe<PropertyChangedEventArgs>( WeakSubscriptionManager.Subscribe(
inpc, inpc,
nameof(inpc.PropertyChanged), nameof(inpc.PropertyChanged),
this); this);

2
src/Markup/Avalonia.Markup/Data/PropertyAccessorNode.cs

@ -37,7 +37,7 @@ namespace Avalonia.Markup.Data
protected override IObservable<object> StartListeningCore(WeakReference reference) protected override IObservable<object> StartListeningCore(WeakReference reference)
{ {
var plugin = ExpressionObserver.PropertyAccessors.FirstOrDefault(x => x.Match(reference)); var plugin = ExpressionObserver.PropertyAccessors.FirstOrDefault(x => x.Match(reference.Target, PropertyName));
var accessor = plugin?.Start(reference, PropertyName); var accessor = plugin?.Start(reference, PropertyName);
if (_enableValidation && Next == null) if (_enableValidation && Next == null)

12
tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_AvaloniaProperty.cs

@ -30,6 +30,16 @@ namespace Avalonia.Markup.UnitTests.Data
Assert.Null(((IAvaloniaObjectDebug)data).GetPropertyChangedSubscribers()); Assert.Null(((IAvaloniaObjectDebug)data).GetPropertyChangedSubscribers());
} }
[Fact]
public async Task Should_Get_Simple_ClrProperty_Value()
{
var data = new Class1();
var target = new ExpressionObserver(data, "ClrProperty");
var result = await target.Take(1);
Assert.Equal("clr-property", result);
}
[Fact] [Fact]
public void Should_Track_Simple_Property_Value() public void Should_Track_Simple_Property_Value()
{ {
@ -69,6 +79,8 @@ namespace Avalonia.Markup.UnitTests.Data
{ {
public static readonly StyledProperty<string> FooProperty = public static readonly StyledProperty<string> FooProperty =
AvaloniaProperty.Register<Class1, string>("Foo", defaultValue: "foo"); AvaloniaProperty.Register<Class1, string>("Foo", defaultValue: "foo");
public string ClrProperty { get; } = "clr-property";
} }
} }
} }

Loading…
Cancel
Save