public T Execute <T>(Instantiable def) where T : GameCollision
        {
            var collision = Object.Instantiate(def.GetPrefab()).GetComponent <T>();

            AddCollision(collision);
            return(collision);
        }
Beispiel #2
0
            public InjectorTypeNameInfo(Type type, string name, InjectorSettings settings)
            {
                Type             = type;
                InstantiableName = name;
                Instantiable definition = null;

                #region Definitions
                if (type.IsInterface)
                {
                    definition = settings.GetInterfaceInstanceDefinition(type.AssemblyQualifiedName, name);
                }
                else if (type.IsAbstract)
                {
                    definition = settings.GetAbstractInstanceDefinition(type.AssemblyQualifiedName, name);
                }
                else if (type.IsClass)
                {
                    definition = settings.GetInstantiableClassDefinition(type.AssemblyQualifiedName).FirstOrDefault(i => i.Name == name);
                    if (definition == null)
                    {
                        definition = new Instantiable {
                            Type = type.AssemblyQualifiedName, Name = name
                        }
                    }
                    ;
                }
                Definition = definition;
                #endregion

                Singleton = definition.Singleton;
                var defType = Core.GetType(definition.Type, true);
                if (defType is null)
                {
                    return;
                }
                InstantiableType = defType;

                ConstructorInfo selectedCtor = null;

                #region Constructor Selector
                var ctors = defType.GetConstructors();
                if (definition.Parameters == null || definition.Parameters.Count == 0)
                {
                    #region .ctor Selector
                    var lstParams = new List <string>();
                    var ctorsOrdersByParamLength = ctors.OrderByDescending(i => i.GetParameters().Length);
                    foreach (var ctor in ctorsOrdersByParamLength)
                    {
                        selectedCtor = ctor;
                        var ctorParameters = ctor.GetParameters();
                        foreach (var ctorParam in ctorParameters)
                        {
                            var paramType       = ctorParam.ParameterType;
                            var paramTypeAQName = paramType.AssemblyQualifiedName;

                            if (ctorParam.HasDefaultValue)
                            {
                                continue;
                            }

                            if (paramType.IsInterface && settings.GetInterfaceDefinition(paramTypeAQName) == null)
                            {
                                selectedCtor = null;
                                lstParams.Add($"A definition for interface: '{paramTypeAQName}' wasn't found.");
                                break;
                            }
                            else if (paramType.IsAbstract && settings.GetAbstractDefinition(paramTypeAQName) == null)
                            {
                                selectedCtor = null;
                                lstParams.Add($"A definition for abstract: '{paramTypeAQName}' wasn't found.");
                                break;
                            }
                            else if (paramType.IsClass && !settings.GetInstantiableClassDefinition(paramTypeAQName).Any())
                            {
                                selectedCtor = null;
                                lstParams.Add($"A definition for class: '{paramTypeAQName}' wasn't found.");
                                break;
                            }
                        }
                        if (selectedCtor != null)
                        {
                            break;
                        }
                    }
                    #endregion

                    if (selectedCtor == null)
                    {
                        throw new Exception($"A valid .ctor wasn't found in the type: {defType.AssemblyQualifiedName}.\r\n{lstParams.Join("\r\n")}");
                    }
                }
                else
                {
                    selectedCtor = ctors.FirstOrDefault(c =>
                    {
                        var cParams = c.GetParameters();
                        var definitionParameters = definition.Parameters.ToDictionary(k => k.Name);
                        foreach (var cParam in cParams)
                        {
                            if (!definitionParameters.Remove(cParam.Name))
                            {
                                if (!cParam.HasDefaultValue)
                                {
                                    return(false);
                                }
                            }
                        }
                        return(definitionParameters.Count == 0);
                    });

                    if (selectedCtor == null)
                    {
                        throw new Exception($"A .ctor with {definition.Parameters.Count} parameters wasn't found in the type: {defType.AssemblyQualifiedName}.");
                    }
                }
                #endregion

                #region Create Expression
                var serExpressions = new List <Expression>();
                var varExpressions = new List <ParameterExpression>();
                var value          = Expression.Parameter(defType, "value");
                varExpressions.Add(value);
                var returnTarget = Expression.Label(typeof(object), "ReturnTarget");

                #region New Call
                var paramExpressions = new List <Expression>();
                var cParameters      = selectedCtor.GetParameters();
                var defParameters    = definition.Parameters.ToDictionary(k => k.Name);
                foreach (var cParam in cParameters)
                {
                    if (defParameters.TryGetValue(cParam.Name, out var defParam))
                    {
                        Argument defArgument = defParam;
                        if (!string.IsNullOrWhiteSpace(defParam.ArgumentName))
                        {
                            settings.Arguments.TryGet(defParam.ArgumentName, out defArgument);
                        }

                        switch (defArgument.Type)
                        {
                        case ArgumentType.Abstract:
                        case ArgumentType.Instance:
                        case ArgumentType.Interface:
                            paramExpressions.Add(
                                Expression.Convert(
                                    Expression.Call(
                                        Expression.Property(null, typeof(Core), "Injector"),
                                        "New",
                                        null,
                                        Expression.Constant(Core.GetType(defArgument.Value), typeof(Type)),
                                        Expression.Constant(defArgument.ClassName, typeof(string))),
                                    cParam.ParameterType)
                                );

                            break;

                        case ArgumentType.Raw:
                            var rawValue = defArgument.Value.ParseTo(cParam.ParameterType, cParam.ParameterType.IsValueType ? System.Activator.CreateInstance(cParam.ParameterType) : null);
                            paramExpressions.Add(Expression.Constant(rawValue, cParam.ParameterType));
                            break;

                        case ArgumentType.Settings:
                            if (Core.Settings.TryGet(defArgument.Value, out var setKeyValue))
                            {
                                var setValue = setKeyValue.Value.ParseTo(cParam.ParameterType, cParam.ParameterType.IsValueType ? System.Activator.CreateInstance(cParam.ParameterType) : null);
                                paramExpressions.Add(Expression.Constant(setValue, cParam.ParameterType));
                            }
                            else
                            {
                                paramExpressions.Add(Expression.Constant(cParam.ParameterType.IsValueType ? System.Activator.CreateInstance(cParam.ParameterType) : null, cParam.ParameterType));
                            }
                            break;
                        }
                    }
                    else if (cParam.HasDefaultValue)
                    {
                        paramExpressions.Add(Expression.Constant(cParam.RawDefaultValue, cParam.ParameterType));
                    }
                }
                if (paramExpressions.Count == 0)
                {
                    serExpressions.Add(Expression.Assign(value, Expression.New(selectedCtor)));
                }
                else
                {
                    serExpressions.Add(Expression.Assign(value, Expression.New(selectedCtor, paramExpressions)));
                }
                #endregion

                #region Properties Set
                if (definition.PropertiesSets?.Any() == true)
                {
                    foreach (var set in definition.PropertiesSets)
                    {
                        Argument argSet = set;
                        if (!string.IsNullOrWhiteSpace(set.ArgumentName))
                        {
                            settings.Arguments.TryGet(set.ArgumentName, out argSet);
                        }

                        var property = defType.GetProperty(set.Name, BindingFlags.Instance | BindingFlags.Public);
                        if (property == null)
                        {
                            throw new Exception($"The Property '{set.Name}' can't be found in the object type '{definition.Type}'");
                        }

                        var propertyExpression = Expression.Property(value, property);

                        switch (argSet.Type)
                        {
                        case ArgumentType.Abstract:
                        case ArgumentType.Instance:
                        case ArgumentType.Interface:
                            serExpressions.Add(
                                Expression.Assign(propertyExpression,
                                                  Expression.Convert(
                                                      Expression.Call(
                                                          Expression.Property(null, typeof(Core), "Injector"),
                                                          "New",
                                                          null,
                                                          Expression.Constant(Core.GetType(argSet.Value), typeof(Type)),
                                                          Expression.Constant(argSet.ClassName, typeof(string))),
                                                      property.PropertyType)
                                                  )
                                );
                            break;

                        case ArgumentType.Raw:
                            var rawValue = argSet.Value.ParseTo(property.PropertyType, property.PropertyType.IsValueType ? System.Activator.CreateInstance(property.PropertyType) : null);
                            serExpressions.Add(Expression.Assign(propertyExpression, Expression.Constant(rawValue, property.PropertyType)));
                            break;

                        case ArgumentType.Settings:
                            if (Core.Settings.TryGet(argSet.Value, out var setKeyValue))
                            {
                                var setValue = setKeyValue.Value.ParseTo(property.PropertyType, property.PropertyType.IsValueType ? System.Activator.CreateInstance(property.PropertyType) : null);
                                serExpressions.Add(Expression.Assign(propertyExpression, Expression.Constant(setValue, property.PropertyType)));
                            }
                            else
                            {
                                serExpressions.Add(Expression.Assign(propertyExpression, Expression.Constant(property.PropertyType.IsValueType ? System.Activator.CreateInstance(property.PropertyType) : null, property.PropertyType)));
                            }
                            break;
                        }
                    }
                }
                #endregion

                serExpressions.Add(Expression.Return(returnTarget, value, typeof(object)));
                serExpressions.Add(Expression.Label(returnTarget, value));
                var block  = Expression.Block(varExpressions, serExpressions).Reduce();
                var lambda = Expression.Lambda <Func <object> >(block, type.Name + "_Activator", null);
                ActivatorExpression = lambda;
                Activator           = lambda.Compile();
                #endregion

                ActivatorByExpression = true;

                if (Singleton)
                {
                    SingletonValue       = Activator();
                    SettedSingletonValue = true;
                }
            }