internal Array InternalResolveInstancesAsArray(Type interfaceType, Action <string> progressCallback, ComponentDescriptor[] resolveStack)
 {
     object[] Components = this.InternalResolveInstances(interfaceType, progressCallback, resolveStack).ToArray();
     return(ComponentContainer.ToTypedArray(interfaceType, Components));
 }
示例#2
0
        internal override async Task <object> CreateInstanceAsync(Type interfaceType, ComponentContainer componentContainer, Action <string> progressCallback, ComponentDescriptor[] resolveStack)
        {
            await this.instanceLock.WaitAsync();

            try
            {
                return(this.instance ?? (this.instance = await this.DoCreateInstanceAsync(interfaceType, componentContainer, progressCallback, resolveStack)));
            }
            finally
            {
                this.instanceLock.Release();
            }
        }
 internal async Task <Array> InternalResolveInstancesAsArrayAsync(Type interfaceType, Action <string> progressCallback, ComponentDescriptor[] resolveStack)
 {
     object[] Components = (await this.InternalResolveInstancesAsync(interfaceType, progressCallback, resolveStack)).ToArray();
     return(ComponentContainer.ToTypedArray(interfaceType, Components));
 }
 internal virtual void Dispose(ComponentContainer componentContainer)
 {
     this.CheckDisposed();
     this.disposed = true;
 }
 internal abstract object CreateInstance(Type interfaceType, ComponentContainer componentContainer, Action <string> progressCallback, ComponentDescriptor[] resolveStack);
        /// <summary>
        ///
        /// </summary>
        private bool CanGetParametersFor(ConstructorInfo constructor, ComponentContainer componentContainer, out string diagnosisInformation)
        {
            foreach (ParameterInfo Parameter in constructor.GetParameters())
            {
                Type ParameterType = Parameter.ParameterType;

                if (ComponentInstance.IsValidInterfaceReference(ParameterType))
                {
                    //Simple interface reference
                    if (this.CheckInterfaceParameter(componentContainer, ParameterType, true, $"{ParameterType.Name} {Parameter.Name}", "a", out diagnosisInformation) == false)
                    {
                        return(false);
                    }
                }
                else if (ComponentInstance.IsValidInterfaceTaskReference(ParameterType))
                {
                    //Task to Simple interface reference
                    if (this.CheckInterfaceParameter(componentContainer, ParameterType.GenericTypeArguments[0], true, $"{ParameterType.Name} {Parameter.Name}", "a", out diagnosisInformation) == false)
                    {
                        return(false);
                    }
                }
                else if (ComponentInstance.IsValidFuncToInterfaceReference(ParameterType))
                {
                    //Func<> Interface reference
                    if (this.CheckInterfaceParameter(componentContainer, ParameterType.GenericTypeArguments[0], true, $"{ParameterType.Name} {Parameter.Name}", "Func<> returning a", out diagnosisInformation) == false)
                    {
                        return(false);
                    }
                }
                else if (ComponentInstance.IsValidInterfaceArrayReference(ParameterType))
                {
                    //Array of interface
                    if (this.CheckInterfaceParameter(componentContainer, ParameterType.GetElementType(), false, $"{ParameterType.Name} {Parameter.Name}", "an array of a", out diagnosisInformation) == false)
                    {
                        return(false);
                    }
                }
                else if (ComponentInstance.IsValidInterfaceArrayTaskReference(ParameterType))
                {
                    //Task to Array of interface
                    if (this.CheckInterfaceParameter(componentContainer, ParameterType.GenericTypeArguments[0].GetElementType(), false, $"{ParameterType.Name} {Parameter.Name}", "an array of a", out diagnosisInformation) == false)
                    {
                        return(false);
                    }
                }
                else if (ComponentInstance.IsValidFuncToInterfaceArrayReference(ParameterType))
                {
                    //Func<> of Array of interface
                    if (this.CheckInterfaceParameter(componentContainer, ParameterType.GenericTypeArguments[0].GetElementType(), false, $"{ParameterType.Name} {Parameter.Name}", "a Func<> returning an array of a", out diagnosisInformation) == false)
                    {
                        return(false);
                    }
                }
                else if (ParameterType == typeof(ComponentRepository))
                {
                    //Parameter is OK
                }
                else if (ParameterType == typeof(ComponentContainer))
                {
                    //Parameter is OK
                }
                else if (this.Descriptor.ConfigType != null && ParameterType.IsAssignableFrom(this.Descriptor.ConfigType))
                {
                    //Parameter is OK
                }
                else
                {
                    diagnosisInformation = $"parameter '{ParameterType.Name} {Parameter.Name}' type not supported. Except component interfaces, arrays of component interfaces, Func<> returning component interfaces or arrays of them or Tasks returning the above, only ComponentRepository, ComponentContainer and the 'Config' Type using in component registration (if given) can be used.";
                    return(false);
                }
            }

            diagnosisInformation = "OK";
            return(true);
        }
        private IEnumerable <T> GetParametersFor <T>(ConstructorInfo constructor, ComponentContainer componentContainer, Action <string> progressCallback, ComponentDescriptor[] resolveStack,
                                                     Func <object, T> wrapResult,
                                                     Func <Type, string, T> createInstance,
                                                     Func <Type, string, T> createInstances
                                                     )
        {
            async Task <object> CreateInstanceArrayAsync(Type parameterType)
            {
                Array Instances = await componentContainer.InternalResolveInstancesAsArrayAsync(parameterType, progressCallback, resolveStack);

                return(Instances);
            }

            List <T> Parameters = new List <T>();

            foreach (ParameterInfo Parameter in constructor.GetParameters())
            {
                Type ParameterType = Parameter.ParameterType;
                if (ComponentInstance.IsValidInterfaceReference(ParameterType))
                {
                    T Component = createInstance(ParameterType, Parameter.Name);
                    Parameters.Add(Component);
                }
                else if (ComponentInstance.IsValidInterfaceTaskReference(ParameterType))
                {
                    object Component = ComponentInstance.DoDynamicCastAsync(ParameterType, componentContainer.InternalResolveInstanceAsync(ParameterType.GenericTypeArguments[0], true, null, new ComponentDescriptor[0]));

                    Parameters.Add(wrapResult(Component));
                }
                else if (ComponentInstance.IsValidFuncToInterfaceReference(ParameterType))
                {
                    LambdaExpression Lambda = Expression.Lambda(
                        ParameterType,
                        Expression.Convert(
                            ((Expression <Func <object> >)(() => componentContainer.InternalResolveInstance(ParameterType.GenericTypeArguments[0], true, progressCallback, new ComponentDescriptor[0]))).Body,
                            ParameterType.GenericTypeArguments[0]));

                    Parameters.Add(wrapResult(Lambda.Compile()));
                }
                else if (ComponentInstance.IsValidInterfaceArrayReference(ParameterType))
                {
                    Parameters.Add(createInstances(ParameterType, Parameter.Name));
                }
                else if (ComponentInstance.IsValidInterfaceArrayTaskReference(ParameterType))
                {
                    object Component = ComponentInstance.DoDynamicCastAsync(ParameterType, CreateInstanceArrayAsync(ParameterType.GenericTypeArguments[0].GetElementType()));
                    Parameters.Add(wrapResult(Component));
                }
                else if (ComponentInstance.IsValidFuncToInterfaceArrayReference(ParameterType))
                {
                    LambdaExpression Lambda = Expression.Lambda(
                        ParameterType,
                        Expression.Convert(
                            ((Expression <Func <Array> >)(() => componentContainer.InternalResolveInstancesAsArray(ParameterType.GenericTypeArguments[0].GetElementType(), progressCallback, new ComponentDescriptor[0]))).Body,
                            ParameterType.GenericTypeArguments[0]));

                    Parameters.Add(wrapResult(Lambda.Compile()));
                }
                else if (ParameterType == typeof(ComponentRepository))
                {
                    Parameters.Add(wrapResult(this.Descriptor.PrivateRepository ?? this.Descriptor.Repository));
                }
                else if (ParameterType == typeof(ComponentContainer))
                {
                    Parameters.Add(wrapResult(componentContainer));
                }
                else if (ParameterType.IsAssignableFrom(this.Descriptor.ConfigType))
                {
                    Parameters.Add(wrapResult(this.Descriptor.Config));
                }
                else
                {
                    throw new InvalidOperationException("Internal error: tried to resolve constructor parameters even though the constructor wasn't adequate");
                }
            }
            return(Parameters);
        }
        /// <summary>
        /// Gets the parameter list to call the given constructor. If a parameter could not be
        /// resolved, null is returned
        /// </summary>
        private async Task <object[]> GetParametersForAsync(ConstructorInfo constructor, ComponentContainer componentContainer, Action <string> progressCallback, ComponentDescriptor[] resolveStack)
        {
            Task <Object> WrapResult(object value)
            {
                return(Task.FromResult(value));
            }

            // ReSharper disable once ParameterOnlyUsedForPreconditionCheck.Local
            async Task <object> CreateInstance(Type parameterType, string parameterName)
            {
                object Instance = await componentContainer.InternalResolveInstanceAsync(parameterType, true, progressCallback, resolveStack);

                Instance.DbC_AssureNotNull($"Could not resolve component '{this.Descriptor.Type.FullName}' even though resolver claimed that he can. Parameter '{parameterName}' (type providing '{parameterType.FullName}' implementation) could not be instanciated");
                return(Instance);
            }

            async Task <object> CreateInstances(Type parameterType, string parameterName)
            {
                Array Instance = await componentContainer.InternalResolveInstancesAsArrayAsync(parameterType.GetElementType(), progressCallback, resolveStack);

                return(Instance);
            }

            return(await Task.WhenAll(this.GetParametersFor(constructor, componentContainer, progressCallback, resolveStack, WrapResult, CreateInstance, CreateInstances)));
        }