<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;

namespace Discord.Commands
{
    internal static class ReflectionUtils
    {
        private static readonly TypeInfo _objectTypeInfo = typeof(object).GetTypeInfo();

        internal static T CreateObject<T>(TypeInfo typeInfo, CommandService commands, IServiceProvider services = null)
            => CreateBuilder<T>(typeInfo, commands)(services);
        internal static Func<IServiceProvider, T> CreateBuilder<T>(TypeInfo typeInfo, CommandService commands)
        {
            var constructor = GetConstructor(typeInfo);
            var parameters = constructor.GetParameters();
            var properties = GetProperties(typeInfo);

            return (services) =>
            {
                var args = new object[parameters.Length];
                for (int i = 0; i < parameters.Length; i++)
                    args[i] = GetMember(commands, services, parameters[i].ParameterType, typeInfo);
                var obj = InvokeConstructor<T>(constructor, args, typeInfo);

                foreach(var property in properties)
                    property.SetValue(obj, GetMember(commands, services, property.PropertyType, typeInfo));
                return obj;
            };
        }
        private static T InvokeConstructor<T>(ConstructorInfo constructor, object[] args, TypeInfo ownerType)
        {
            try
            {
                return (T)constructor.Invoke(args);
            }
            catch (Exception ex)
            {
                throw new Exception($"Failed to create \"{ownerType.FullName}\"", ex);
            }
        }

        private static ConstructorInfo GetConstructor(TypeInfo ownerType)
        {
            var constructors = ownerType.DeclaredConstructors.Where(x => !x.IsStatic).ToArray();
            if (constructors.Length == 0)
                throw new InvalidOperationException($"No constructor found for \"{ownerType.FullName}\"");
            else if (constructors.Length > 1)
                throw new InvalidOperationException($"Multiple constructors found for \"{ownerType.FullName}\"");
            return constructors[0];
        }
        private static System.Reflection.PropertyInfo[] GetProperties(TypeInfo ownerType)
        {
            var result = new List<System.Reflection.PropertyInfo>();
            while (ownerType != _objectTypeInfo)
            {
                foreach (var prop in ownerType.DeclaredProperties)
                {
                    if (!prop.GetMethod.IsStatic && prop.SetMethod?.IsPublic == true && prop.GetCustomAttribute<DontInjectAttribute>() == null)
                        result.Add(prop);
                }
                ownerType = ownerType.BaseType.GetTypeInfo();
            }
            return result.ToArray();
        }
        private static object GetMember(CommandService commands, IServiceProvider services, Type memberType, TypeInfo ownerType)
        {
            if (memberType == typeof(CommandService))
                return commands;
            if (memberType == typeof(IServiceProvider) || memberType == services.GetType())
                return services;
            var service = services?.GetService(memberType);
            if (service != null)
                return service;
            throw new InvalidOperationException($"Failed to create \"{ownerType.FullName}\", dependency \"{memberType.Name}\" was not found.");
        }
    }
}<commit_msg>Fix the off-chance that someone has a property without a getter<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;

namespace Discord.Commands
{
    internal static class ReflectionUtils
    {
        private static readonly TypeInfo _objectTypeInfo = typeof(object).GetTypeInfo();

        internal static T CreateObject<T>(TypeInfo typeInfo, CommandService commands, IServiceProvider services = null)
            => CreateBuilder<T>(typeInfo, commands)(services);
        internal static Func<IServiceProvider, T> CreateBuilder<T>(TypeInfo typeInfo, CommandService commands)
        {
            var constructor = GetConstructor(typeInfo);
            var parameters = constructor.GetParameters();
            var properties = GetProperties(typeInfo);

            return (services) =>
            {
                var args = new object[parameters.Length];
                for (int i = 0; i < parameters.Length; i++)
                    args[i] = GetMember(commands, services, parameters[i].ParameterType, typeInfo);
                var obj = InvokeConstructor<T>(constructor, args, typeInfo);

                foreach(var property in properties)
                    property.SetValue(obj, GetMember(commands, services, property.PropertyType, typeInfo));
                return obj;
            };
        }
        private static T InvokeConstructor<T>(ConstructorInfo constructor, object[] args, TypeInfo ownerType)
        {
            try
            {
                return (T)constructor.Invoke(args);
            }
            catch (Exception ex)
            {
                throw new Exception($"Failed to create \"{ownerType.FullName}\"", ex);
            }
        }

        private static ConstructorInfo GetConstructor(TypeInfo ownerType)
        {
            var constructors = ownerType.DeclaredConstructors.Where(x => !x.IsStatic).ToArray();
            if (constructors.Length == 0)
                throw new InvalidOperationException($"No constructor found for \"{ownerType.FullName}\"");
            else if (constructors.Length > 1)
                throw new InvalidOperationException($"Multiple constructors found for \"{ownerType.FullName}\"");
            return constructors[0];
        }
        private static System.Reflection.PropertyInfo[] GetProperties(TypeInfo ownerType)
        {
            var result = new List<System.Reflection.PropertyInfo>();
            while (ownerType != _objectTypeInfo)
            {
                foreach (var prop in ownerType.DeclaredProperties)
                {
                    if (prop.GetMethod?.IsStatic == false && prop.SetMethod?.IsPublic == true && prop.GetCustomAttribute<DontInjectAttribute>() == null)
                        result.Add(prop);
                }
                ownerType = ownerType.BaseType.GetTypeInfo();
            }
            return result.ToArray();
        }
        private static object GetMember(CommandService commands, IServiceProvider services, Type memberType, TypeInfo ownerType)
        {
            if (memberType == typeof(CommandService))
                return commands;
            if (memberType == typeof(IServiceProvider) || memberType == services.GetType())
                return services;
            var service = services?.GetService(memberType);
            if (service != null)
                return service;
            throw new InvalidOperationException($"Failed to create \"{ownerType.FullName}\", dependency \"{memberType.Name}\" was not found.");
        }
    }
}
{'fraction_non_alphanumeric': 0.09410288582183186, 'fraction_numerical': 0.0011152934615920815, 'mean_word_length': 2.1520210896309315, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 27, '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': '822506', 'n_tokens_mistral': 1671, 'n_tokens_neox': 1637, 'n_words': 429}