<commit_before>﻿using System;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reactive.Linq;

namespace Flip
{
    /// <summary>
    /// <see cref="IObservable{T}"/> 인터페이스와
    /// <see cref="INotifyPropertyChanged"/> 인터페이스를 지원하는
    /// 메서드 집합을 제공합니다.
    /// </summary>
    public static class ObservableExtensions
    {
        private static string GetMemberName(Expression expression)
        {
            var body = expression as MemberExpression;
            if (body != null)
            {
                return body.Member.Name;
            }
            if (expression.NodeType == ExpressionType.Convert)
            {
                var unaryExpression = expression as UnaryExpression;
                body = unaryExpression.Operand as MemberExpression;
                if (body != null)
                {
                    return body.Member.Name;
                }
            }
            return null;
        }

        private static IObservable<TProperty> ObserveImpl
            <TComponent, TProperty>(
            TComponent component,
            Expression<Func<TComponent, TProperty>> propertyExpression)
            where TComponent : INotifyPropertyChanged
        {
            var propertyName = GetMemberName(propertyExpression.Body);
            if (propertyName == null)
            {
                throw new ArgumentException(
                    "The expression is not a property expression.",
                    paramName: nameof(propertyExpression));
            }

            var compiled = propertyExpression.Compile();

            var source = Observable.FromEventPattern<PropertyChangedEventArgs>(
                component, nameof(component.PropertyChanged));

            return Observable
                .Start(() => compiled.Invoke(component))
                .Concat(from e in source
                        where e.EventArgs.PropertyName == propertyName
                        select compiled.Invoke(component));
        }

        /// <summary>
        /// <see cref="INotifyPropertyChanged"/> 인터페이스 구현체의
        /// 지정한 속성을 관찰합니다.
        /// </summary>
        /// <typeparam name="TComponent">
        /// <see cref="INotifyPropertyChanged"/> 인터페이스 구현체 형식입니다.
        /// </typeparam>
        /// <typeparam name="TProperty">관찰할 속성의 형식입니다.</typeparam>
        /// <param name="component"><see cref="INotifyPropertyChanged"/>
        /// 인터페이스 구현체입니다.
        /// </param>
        /// <param name="propertyExpression"><commit_msg>사소한 코드 정리<commit_after>﻿using System;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Reactive.Linq;

namespace Flip
{
    /// <summary>
    /// <see cref="IObservable{T}"/> 인터페이스와
    /// <see cref="INotifyPropertyChanged"/> 인터페이스를 지원하는
    /// 메서드 집합을 제공합니다.
    /// </summary>
    public static class ObservableExtensions
    {
        private static string GetMemberName(Expression expression)
        {
            var body = expression as MemberExpression;
            if (body != null)
            {
                return body.Member.Name;
            }
            if (expression.NodeType == ExpressionType.Convert)
            {
                var unaryExpression = expression as UnaryExpression;
                body = unaryExpression.Operand as MemberExpression;
                if (body != null)
                {
                    return body.Member.Name;
                }
            }
            return null;
        }

        private static IObservable<TProperty> ObserveImpl
            <TComponent, TProperty>(
            TComponent component,
            Expression<Func<TComponent, TProperty>> propertyExpression)
            where TComponent : INotifyPropertyChanged
        {
            string propertyName = GetMemberName(propertyExpression.Body);
            if (propertyName == null)
            {
                throw new ArgumentException(
                    "The expression is not a property expression.",
                    paramName: nameof(propertyExpression));
            }

            Func<TComponent, TProperty> compiled = propertyExpression.Compile();

            IObservable<TComponent> source =
                from e in Observable.FromEventPattern<PropertyChangedEventArgs>(
                    component, nameof(component.PropertyChanged))
                where e.EventArgs.PropertyName == propertyName
                select component;

            return Observable
                .Start(() => compiled.Invoke(component))
                .Concat(source.Select(compiled));
        }

        /// <summary>
        /// <see cref="INotifyPropertyChanged"/> 인터페이스 구현체의
        /// 지정한 속성을 관찰합니다.
        /// </summary>
        /// <typeparam name="TComponent">
        /// <see cref="INotifyPropertyChanged"/> 인터페이스 구현체 형식입니다.
        /// </typeparam>
        /// <typeparam name="TProperty">관찰할 속성의 형식입니다.</typeparam>
        /// <param name="component"><see cref="INotifyPropertyChanged"/>
        /// 인터페이스 구현체입니다.
        /// </param>
        /// <param name="propertyExpression">
{'fraction_non_alphanumeric': 0.1010752688172043, 'fraction_numerical': 0.0, 'mean_word_length': 1.6785340314136126, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1672688', 'n_tokens_mistral': 1365, 'n_tokens_neox': 1465, 'n_words': 290}