private DependencyLocator GetNewLocator_Func_5 <T1, T2, T3, T4, TResult>(ActivatorTree tree)
        {
            tree = new ActivatorTree(tree, tree.Context.Get(typeof(TResult), new MethodSignature(typeof(T1), typeof(T2), typeof(T3), typeof(T4))));
            var locator = GetLocator(tree);

            return((c, a) => new Func <T1, T2, T3, T4, TResult>((t1, t2, t3, t4) => (TResult)locator(c, new object[] { t1, t2, t3, t4 })));
        }
        private DependencyLocator GetNewLocator_Func_2 <T, TResult>(ActivatorTree tree)
        {
            tree = new ActivatorTree(tree, tree.Context.Get(typeof(TResult), new MethodSignature(typeof(T))));
            var locator = GetLocator(tree);

            return((c, a) => new Func <T, TResult>((t) => (TResult)locator(c, new object[] { t })));
        }
        private DependencyLocator GetNewLocator_Func_1 <T>(ActivatorTree tree)
        {
            tree = new ActivatorTree(tree, tree.Context.Get(typeof(T)));
            var locator = GetLocator(tree);

            return((c, a) => new Func <T>(() => (T)locator(c, a)));
        }
        public void Inject(object obj, object[] args, IRuntimeImportContext ctx)
        {
            var tree = new ActivatorTree(null, ctx.StaticContext);

            tree.Key = new ActivatorKey(obj.GetType(), null);
            var injectors = GetClassInjector(tree);

            injectors.Item1(ctx, args, obj);
            injectors.Item2(ctx, args, obj);
        }
        private DependencyLocator GetNewLocator_IEnumerable_1 <T>(IActivatorTree tree)
        {
            Action <IRuntimeImportContext, object[], List <T> > action = (c, a, l) => {};

            var testTree = new ActivatorTree(tree, tree.Context.Get(typeof(T)));

            foreach (var e in _locatorEntries.Where(l => l.Test(testTree)).ToList())
            {
                var activator = e.Locator(new ActivatorTree(tree, tree.Context.Get(typeof(T))));

                action += (c, a, l) => l.Add((T)activator(c, a));
            }
            return((c, a) =>
            {
                var l = new List <T>();
                action(c, a, l);
                return l;
            });
        }
        private DependencyLocator GetNewLocator(IActivatorTree tree)
        {
            var importType = tree.Context.ImportType;

            if (importType.IsGenericType)
            {
                var g    = importType.GetGenericTypeDefinition();
                var args = importType.GetGenericArguments();

                // return a Func<Type,object> to provide generic locator without arguments
                if (args.Length == 2 && args[0] == typeof(Type) && args[1] == typeof(object))
                {
                    return((c, a) => new Func <Type, object>(t => Locate(c.Get(c.Target, tree.Context.Get(t, null)))));
                }

                //return a Func<Type,object[],object> to provide a generic locator with arguments
                if (args.Length == 3 && args[0] == typeof(Type) && args[1] == typeof(object[]) && args[2] == typeof(object))
                {
                    return((c, a) => new Func <Type, object[], object>((t, ar) =>
                    {
                        var types = new MethodSignature(ar);
                        return Locate(c.Get(c.Target, tree.Context.Get(t, types)), ar);
                    }));
                }

                var name = g.Name.Split('`')[0];

                var mi = GetType().GetMethod("GetNewLocator_" + name + "_" + args.Length, BindingFlags.NonPublic | BindingFlags.Instance);
                if (mi != null)
                {
                    var m = mi.MakeGenericMethod(args);

                    var r = m?.Invoke(this, new object[] { tree });

                    if (r is DependencyLocator l)
                    {
                        return(l);
                    }

                    throw new Exception("");
                }
            }

            {
                var decorators = _decoratorEntries.Where(e => e.Test(tree));

                var exportEntry = _locatorEntries.Get(e => e.Test(tree));


                //if (tree.Context.ImportType.Name.Contains("ErpServices"))
                //{
                //    foreach (var e in _locatorEntries)
                //    {
                //        if (e.ExportType(tree).Name.Contains("ErpServices"))
                //        { }
                //        var r = e.Test(tree);
                //    }
                //}


                IActivatorKey export;
                ExportMode    mode;

                // when no export entry found but type is instantiable use it TODO : should be an option
                if (exportEntry == null)
                {
                    if (!importType.IsAbstract && !importType.IsInterface)
                    {
                        exportEntry = new ExportEntry(this)
                        {
                            ExportType = t => importType
                        };

                        export = new ActivatorKey(importType, tree.Context.Signature);
                        mode   = ExportMode.Default;
                    }
                    else
                    {
                        var t = new ActivatorTree(null, new ImportContext());
                        var n = _locatorEntries.Get(e =>
                        {
                            try
                            {
                                var exportType = e.ExportType(t);
                                return(importType.IsAssignableFrom(exportType));
                            }
                            catch
                            {
                                return(false);
                            }
                        });

                        throw new Exception("Unable to locate " + tree.ToString() /*importType.GenericReadableName()*/);
                    }
                }
                else
                {
                    export = exportEntry.GetActivatorKey(tree);
                    mode   = exportEntry.Mode;
                }

                DependencyLocator activator;
                if (mode.HasFlag(ExportMode.Singleton))
                {
                    var type = export.ReturnType;

                    tree.Key = new ActivatorKey(type, null);

                    var singleton = Singletons.GetOrAdd(type, t => exportEntry.Locator(tree)(RuntimeImportContext.GetStatic(null, tree.Context.ImportType), null));

                    activator = (c, a) => singleton;
                }
                else
                {
                    activator = exportEntry.Locator(tree);
                }


                foreach (var de in decorators)
                {
                    var decorator = de.Locator(new ActivatorTree(tree,
                                                                 tree.Context.Get(importType, new MethodSignature(importType))));

                    var old = activator;

                    activator = (c, a) => decorator(c, new[] { old(c, a) });
                }


                return(activator);
            }
        }