<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

/// <summary>
/// Got this from the following sites :
/// https://vagifabilov.wordpress.com/2010/04/02/dont-use-activator-createinstance-or-constructorinfo-invoke-use-compiled-lambda-expressions/
/// https://ayende.com/blog/3167/creating-objects-perf-implications
/// http://rogeralsing.com/2008/02/28/linq-expressions-creating-objects/
/// https://rboeije.wordpress.com/2012/04/19/extension-method-on-type-as-alternative-for-activator-createinstance/ - Implemented this
/// 
/// This extension is a benchmarked better implementation to Activator.CreateInstance when taking the second link into consideration
/// Here the expression is further cached so as to better instantiation for factory implementations
/// </summary>
internal static class InstanceCreatorExtensions
{
    internal static object New(this Type type, params object[] args)
    {
        Type[] argTypes = args.Select(a => a.GetType()).ToArray();

        ConstructorInfo constructorInfo = type.GetConstructor(argTypes);
        ObjectActivator activator = GetActivator(constructorInfo);

        return activator(args);
    }

    internal delegate object ObjectActivator(params object[] args);

    private static Dictionary<ConstructorInfo, object> _activators = new Dictionary<ConstructorInfo, object>();

    internal static ObjectActivator GetActivator(ConstructorInfo constructorInfo)
    {
        object activator;
        if (_activators.TryGetValue(constructorInfo, out activator)) return (ObjectActivator)activator;

        ParameterInfo[] paramsInfo = constructorInfo.GetParameters();

        //create a single param of type object[]
        ParameterExpression param = Expression.Parameter(typeof(object[]), "args");

        Expression[] argsExp = new Expression[paramsInfo.Length];

        //pick each arg from the params array
        //and create a typed expression of them
        for (int i = 0; i < paramsInfo.Length; i++)
        {
            Expression index = Expression.Constant(i);

            Expression paramAccessorExp = Expression.ArrayIndex(param, index);

            Expression paramCastExp = Expression.Convert(paramAccessorExp, paramsInfo[i].ParameterType);

            argsExp[i] = paramCastExp;
        }

        //make a NewExpression that calls the constructor with the args we just created
        NewExpression newExp = Expression.New(constructorInfo, argsExp);

        //create a lambda with the NewExpression as body and our param object[] as arg
        LambdaExpression lambda = Expression.Lambda(typeof(ObjectActivator), newExp, param);

        //compile it
        ObjectActivator compiled = (ObjectActivator)lambda.Compile();

        _activators.Add(constructorInfo, compiled);

        return compiled;
    }
}<commit_msg>Dictornary type changed to remove casting. changes to format and code arrangement, to be in sync with the rest of Coop's code style<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace DTools.Suice
{
    /// <summary>
    /// Got this from the following sites :
    /// https://vagifabilov.wordpress.com/2010/04/02/dont-use-activator-createinstance-or-constructorinfo-invoke-use-compiled-lambda-expressions/
    /// https://ayende.com/blog/3167/creating-objects-perf-implications
    /// http://rogeralsing.com/2008/02/28/linq-expressions-creating-objects/
    /// https://rboeije.wordpress.com/2012/04/19/extension-method-on-type-as-alternative-for-activator-createinstance/ - Implemented this
    /// 
    /// This extension is a benchmarked better implementation to Activator.CreateInstance when taking the second link into consideration
    /// Here the expression is further cached so as to better instantiation for factory implementations
    /// 
    /// @author ChicK00o
    /// </summary>
    internal static class InstanceCreatorExtensions
    {
        private const string PARAM_NAME = "args";

        private static Dictionary<ConstructorInfo, ObjectActivator> activators =
            new Dictionary<ConstructorInfo, ObjectActivator>();

        private delegate object ObjectActivator(params object[] args);

        internal static object New(this Type type, params object[] args)
        {
            Type[] argTypes = args.Select(a => a.GetType()).ToArray();

            ConstructorInfo constructorInfo = type.GetConstructor(argTypes);
            ObjectActivator activator = GetActivator(constructorInfo);

            return activator(args);
        }

        private static ObjectActivator GetActivator(ConstructorInfo constructorInfo)
        {
            ObjectActivator activator;

            if(activators.TryGetValue(constructorInfo, out activator) == false) {
                activator = CreateNewActivator(constructorInfo);
            }

            return activator;
        }

        private static ObjectActivator CreateNewActivator(ConstructorInfo constructorInfo)
        {
            ParameterInfo[] paramsInfo = constructorInfo.GetParameters();

            //create a single param of type object[]
            ParameterExpression param = Expression.Parameter(typeof(object[]), PARAM_NAME);

            Expression[] argsExp = new Expression[paramsInfo.Length];

            //pick each arg from the params array
            //and create a typed expression of them
            for(int i = 0; i < paramsInfo.Length; i++) {
                Expression index = Expression.Constant(i);
                Expression paramAccessorExp = Expression.ArrayIndex(param, index);
                Expression paramCastExp = Expression.Convert(paramAccessorExp, paramsInfo[i].ParameterType);
                argsExp[i] = paramCastExp;
            }

            //make a NewExpression that calls the constructor with the args we just created
            NewExpression newExp = Expression.New(constructorInfo, argsExp);

            //create a lambda with the NewExpression as body and our param object[] as arg
            LambdaExpression lambda = Expression.Lambda(typeof(ObjectActivator), newExp, param);

            //compile it
            ObjectActivator compiled = (ObjectActivator) lambda.Compile();

            activators.Add(constructorInfo, compiled);

            return compiled;
        }
    }
}
{'fraction_non_alphanumeric': 0.09202740579258797, 'fraction_numerical': 0.009342883836810962, 'mean_word_length': 2.957486136783734, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 6, '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': '5321898', 'n_tokens_mistral': 1635, 'n_tokens_neox': 1535, 'n_words': 444}