Skip to content

Commit 599391a

Browse files
perf: get rid of a couple closures (#103)
* perf: get rid of a couple closures * replace variable abbreviation with proper name Co-authored-by: Glenn <[email protected]>
1 parent 610bf06 commit 599391a

File tree

3 files changed

+41
-21
lines changed

3 files changed

+41
-21
lines changed

src/ReactiveMarbles.PropertyChanged/GetMemberFuncCache.cs

+11-13
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,23 @@ namespace ReactiveMarbles.PropertyChanged
1212
internal static class GetMemberFuncCache<TFrom, TReturn>
1313
{
1414
#if !UIKIT
15-
private static readonly
16-
ConcurrentDictionary<(Type FromType, string MemberName), Func<TFrom, TReturn>> Cache
17-
= new ConcurrentDictionary<(Type, string), Func<TFrom, TReturn>>();
15+
private static readonly ConcurrentDictionary<MemberInfo, Func<TFrom, TReturn>> Cache = new(new MemberFuncCacheKeyComparer());
1816
#endif
1917

2018
public static Func<TFrom, TReturn> GetCache(MemberInfo memberInfo)
2119
{
2220
#if UIKIT
23-
switch (memberInfo)
24-
{
25-
case PropertyInfo propertyInfo:
26-
return input => (TReturn)propertyInfo.GetValue(input);
27-
case FieldInfo fieldInfo:
28-
return input => (TReturn)fieldInfo.GetValue(input);
29-
default:
30-
throw new ArgumentException($"Cannot handle member {memberInfo.Name}", nameof(memberInfo));
31-
}
21+
switch (memberInfo)
22+
{
23+
case PropertyInfo propertyInfo:
24+
return input => (TReturn)propertyInfo.GetValue(input);
25+
case FieldInfo fieldInfo:
26+
return input => (TReturn)fieldInfo.GetValue(input);
27+
default:
28+
throw new ArgumentException($"Cannot handle member {memberInfo.Name}", nameof(memberInfo));
29+
}
3230
#else
33-
return Cache.GetOrAdd((memberInfo.DeclaringType, memberInfo.Name), _ =>
31+
return Cache.GetOrAdd(memberInfo, static memberInfo =>
3432
{
3533
var instance = Expression.Parameter(typeof(TFrom), "instance");
3634

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) 2019-2020 ReactiveUI Association Incorporated. All rights reserved.
2+
// ReactiveUI Association Incorporated licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for full license information.
4+
5+
using System.Collections.Generic;
6+
using System.Reflection;
7+
8+
namespace ReactiveMarbles.PropertyChanged
9+
{
10+
internal sealed class MemberFuncCacheKeyComparer : IEqualityComparer<MemberInfo>
11+
{
12+
public bool Equals(MemberInfo x, MemberInfo y)
13+
{
14+
return (x.DeclaringType, x.Name) == (y.DeclaringType, y.Name);
15+
}
16+
17+
public int GetHashCode(MemberInfo obj)
18+
{
19+
return (obj.DeclaringType, obj.Name).GetHashCode();
20+
}
21+
}
22+
}

src/ReactiveMarbles.PropertyChanged/NotifyPropertyChangedExtensions.cs

+8-8
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,17 @@ public static IObservable<TReturn> WhenPropertyValueChanges<TObj, TReturn>(
7474

7575
if (i == expressionChain.Count - 1)
7676
{
77-
var function = GetMemberFuncCache<INotifyPropertyChanged, TReturn>.GetCache(memberInfo);
78-
return currentObservable
79-
.Where(parent => parent.Value != null)
80-
.Select(parent => GenerateObservable(parent.Value, memberInfo, function))
77+
return Observable.Return(memberInfo)
78+
.CombineLatest(currentObservable, (memberInfo, parent) => (memberInfo, sender: parent.Sender, value: parent.Value))
79+
.Where(x => x.value != null)
80+
.Select(x => GenerateObservable(x.value, x.memberInfo, GetMemberFuncCache<INotifyPropertyChanged, TReturn>.GetCache(x.memberInfo)))
8181
.Switch();
8282
}
8383

84-
var iFunction = GetMemberFuncCache<INotifyPropertyChanged, INotifyPropertyChanged>.GetCache(memberInfo);
85-
currentObservable = currentObservable
86-
.Where(parent => parent.Value != null)
87-
.Select(parent => GenerateObservable(parent.Value, memberInfo, iFunction))
84+
currentObservable = Observable.Return(memberInfo)
85+
.CombineLatest(currentObservable, (memberInfo, parent) => (memberInfo, sender: parent.Sender, value: parent.Value))
86+
.Where(x => x.value != null)
87+
.Select(x => GenerateObservable(x.value, x.memberInfo, GetMemberFuncCache<INotifyPropertyChanged, INotifyPropertyChanged>.GetCache(x.memberInfo)))
8888
.Switch();
8989

9090
i++;

0 commit comments

Comments
 (0)