< Summary

Information
Class: MyNet.Observable.Behaviors.NotifyPropertyChangedSourceSnapshot
Assembly: MyNet.Observable
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Observable/Behaviors/NotifyPropertyChangedSourceSnapshot.cs
Tag: 323_28699572109
Line coverage
100%
Covered lines: 10
Uncovered lines: 0
Coverable lines: 10
Total lines: 68
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
EnumerateValues(...)100%11100%
CreateGetters(...)100%11100%
CompileGetter(...)100%11100%

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.Observable/Behaviors/NotifyPropertyChangedSourceSnapshot.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="NotifyPropertyChangedSourceSnapshot.cs" company="Stéphane ANDRE">
 3// Copyright (c) Stéphane ANDRE. All rights reserved.
 4// </copyright>
 5// -----------------------------------------------------------------------
 6
 7using System;
 8using System.Collections.Concurrent;
 9using System.Collections.Generic;
 10using System.Linq;
 11using System.Linq.Expressions;
 12using System.Reflection;
 13
 14namespace MyNet.Observable.Behaviors;
 15
 16/// <summary>
 17/// Cached compiled getters used when attaching to a wrapper source (attach path only).
 18/// </summary>
 19internal static class NotifyPropertyChangedSourceSnapshot
 20{
 321    private static readonly ConcurrentDictionary<Type, PropertyGetter[]> GetterCache = new();
 22
 23    /// <summary>
 24    /// Enumerates public readable instance property values on the source object.
 25    /// </summary>
 26    public static IEnumerable<(string PropertyName, object? Value)> EnumerateValues(object source)
 27    {
 5128        ArgumentNullException.ThrowIfNull(source);
 29
 5130        return enumerateValues();
 31
 32        IEnumerable<(string PropertyName, object? Value)> enumerateValues()
 33        {
 34            var getters = GetterCache.GetOrAdd(source.GetType(), CreateGetters);
 35
 36            foreach (var entry in getters)
 37                yield return (entry.Name, entry.Getter(source));
 38        }
 39    }
 40
 41    private static PropertyGetter[] CreateGetters(Type type)
 42    {
 643        var list = (from property in type.GetProperties(BindingFlags.Instance | BindingFlags.Public) where property.CanR
 44
 645        return [.. list];
 46    }
 47
 48    private static Func<object, object?> CompileGetter(Type type, PropertyInfo property)
 49    {
 650        var parameter = Expression.Parameter(typeof(object));
 51
 652        var cast = Expression.Convert(parameter, type);
 53
 654        var propertyAccess = Expression.Property(cast, property);
 55
 656        var convert = Expression.Convert(propertyAccess, typeof(object));
 57
 658        return Expression.Lambda<Func<object, object?>>(convert, parameter).Compile();
 59    }
 60
 61    private sealed class PropertyGetter(string name, Func<object, object?> getter)
 62    {
 63        public string Name { get; } = name;
 64
 65        public Func<object, object?> Getter { get; } = getter;
 66    }
 67}
 68