<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;

#if NET45
using System.Threading.Tasks;
#endif

namespace Dehydrator
{
    /// <summary>
    /// Decorator for <see cref="IReadRepository{TEntity}"/> instances that transparently dehydrates references on entities it returns.
    /// </summary>
    public class DehydratingReadRepository<TEntity> : IReadRepository<TEntity>
        where TEntity : class, IEntity, new()
    {
        /// <summary>
        /// The underlying repository this decorater delegates calls to after performing its own processing.
        /// </summary>
        [NotNull] protected readonly IReadRepository<TEntity> Inner;

        /// <summary>
        /// Creates a new reference-dehydrating decorator.
        /// </summary>
        /// <param name="inner">The inner repository to use for the actual storage.</param>
        public DehydratingReadRepository([NotNull] IReadRepository<TEntity> inner)
        {
            Inner = inner;
        }

        public IEnumerable<TEntity> GetAll()
        {
            return Inner.GetAll().Select(x => x.Dehydrate());
        }

        public IEnumerable<TResult> GetAll<TResult>(Func<IQueryable<TEntity>, IQueryable<TResult>> query)
        {
            var result = Inner.GetAll(query);

            // Dehydrate if the query result is a collection of entities, otherwise pass through
            return (typeof(TEntity) == typeof(TResult))
                ? result.Cast<TEntity>().Select(x => x.Dehydrate()).Cast<TResult>()
                : result;
        }

        public TEntity Find(long id)
        {
            return Inner.Find(id)?.DehydrateReferences();
        }

        public bool Exists(long id)
        {
            return Inner.Exists(id);
        }

#if NET45
        public async Task<IReadOnlyCollection<TResult>> QueryAsync<TResult>(Func<IQueryable<TEntity>, IQueryable<TResult>> query)
        {
            var result = await Inner.QueryAsync(query);

            // Dehydrate if the query result is a collection of entities, otherwise pass through
            return (typeof(TEntity) == typeof(TResult))
                ? result.Cast<TEntity>().Select(x => x.DehydrateReferences()).Cast<TResult>().ToList()
                : result;
        }

        public async Task<TResult> FirstAsync<TResult>(Func<IQueryable<TEntity>, IQueryable<TResult>> query)
        {
            var result = await Inner.FirstAsync(query);

            // Dehydrate if the query result is an entity, otherwise pass through
            return (typeof(TEntity) == typeof(TResult))
                ? (TResult)(object)((TEntity)(object)result)?.DehydrateReferences()
                : result;
        }

        public async Task<TResult> FirstOrDefaultAsync<TResult>(Func<IQueryable<TEntity>, IQueryable<TResult>> query)
        {
            var result = await Inner.FirstOrDefaultAsync(query);

            // Dehydrate if the query result is an entity, otherwise pass through
            return (typeof(TEntity) == typeof(TResult))
                ? (TResult)(object)((TEntity)(object)result)?.DehydrateReferences()
                : result;
        }

        public async Task<IEntity> FindUntypedAsync(long id)
        {
            var entity = await Inner.FindAsync(id);
            return entity?.DehydrateReferences();
        }
#endif
    }
}<commit_msg>DehydratingReadRepository: Detect entities in query results more reliably<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;

#if NET45
using System.Threading.Tasks;
#endif

namespace Dehydrator
{
    /// <summary>
    /// Decorator for <see cref="IReadRepository{TEntity}"/> instances that transparently dehydrates references on entities it returns.
    /// </summary>
    public class DehydratingReadRepository<TEntity> : IReadRepository<TEntity>
        where TEntity : class, IEntity, new()
    {
        /// <summary>
        /// The underlying repository this decorater delegates calls to after performing its own processing.
        /// </summary>
        [NotNull] protected readonly IReadRepository<TEntity> Inner;

        /// <summary>
        /// Creates a new reference-dehydrating decorator.
        /// </summary>
        /// <param name="inner">The inner repository to use for the actual storage.</param>
        public DehydratingReadRepository([NotNull] IReadRepository<TEntity> inner)
        {
            Inner = inner;
        }

        public IEnumerable<TEntity> GetAll()
        {
            return Inner.GetAll().Select(x => x.Dehydrate());
        }

        public IEnumerable<TResult> GetAll<TResult>(Func<IQueryable<TEntity>, IQueryable<TResult>> query)
        {
            var result = Inner.GetAll(query);

            // Dehydrate if the query result is a collection of entities, otherwise pass through
            return (typeof(TEntity) == typeof(TResult))
                ? result.Cast<TEntity>().Select(x => x.Dehydrate()).Cast<TResult>()
                : result;
        }

        public TEntity Find(long id)
        {
            return Inner.Find(id)?.DehydrateReferences();
        }

        public bool Exists(long id)
        {
            return Inner.Exists(id);
        }

#if NET45
        public async Task<IReadOnlyCollection<TResult>> QueryAsync<TResult>(Func<IQueryable<TEntity>, IQueryable<TResult>> query)
        {
            var result = await Inner.QueryAsync(query);

            // Dehydrate if the query result is a collection of entities, otherwise pass through
            return IsEntity(typeof(TResult))
                ? result.Cast<TEntity>().Select(x => x.DehydrateReferences()).Cast<TResult>().ToList()
                : result;
        }

        public async Task<TResult> FirstAsync<TResult>(Func<IQueryable<TEntity>, IQueryable<TResult>> query)
        {
            var result = await Inner.FirstAsync(query);

            // Dehydrate if the query result is an entity, otherwise pass through
            return IsEntity(typeof(TResult))
                ? (TResult)(object)((TEntity)(object)result)?.DehydrateReferences()
                : result;
        }

        public async Task<TResult> FirstOrDefaultAsync<TResult>(Func<IQueryable<TEntity>, IQueryable<TResult>> query)
        {
            var result = await Inner.FirstOrDefaultAsync(query);

            // Dehydrate if the query result is an entity, otherwise pass through
            return IsEntity(typeof(TResult))
                ? (TResult)(object)((TEntity)(object)result)?.DehydrateReferences()
                : result;
        }

        private static bool IsEntity(Type type)
        {
            return type == typeof(IEntity) || type.GetInterfaces().Contains(typeof(IEntity));
        }

        public async Task<IEntity> FindUntypedAsync(long id)
        {
            var entity = await Inner.FindAsync(id);
            return entity?.DehydrateReferences();
        }
#endif
    }
}
{'fraction_non_alphanumeric': 0.10752994865944096, 'fraction_numerical': 0.0011409013120365088, 'mean_word_length': 2.323696682464455, 'pattern_counts': {'":': 0, '<': 83, '<?xml version=': 0, '>': 89, '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': '116398', 'n_tokens_mistral': 1962, 'n_tokens_neox': 1855, 'n_words': 457}