Пример #1
0
        public bool TryBuildExpression(IBuildContext buildContext, ILifetime lifetime, out Expression baseExpression, out Exception error)
        {
            if (buildContext == null)
            {
                throw new ArgumentNullException(nameof(buildContext));
            }
            try
            {
                var autoWiringStrategy          = _autoWiringStrategy ?? buildContext.AutowiringStrategy;
                var isDefaultAutoWiringStrategy = DefaultAutowiringStrategy.Shared == autoWiringStrategy;
                if (!autoWiringStrategy.TryResolveType(_type, buildContext.Key.Type, out var instanceType))
                {
                    instanceType = _hasGenericParamsWithConstraints
                        ? GetInstanceTypeBasedOnTargetGenericConstrains(buildContext.Key.Type) ?? buildContext.Container.Resolve <IIssueResolver>().CannotResolveType(_type, buildContext.Key.Type)
                        : _type;
                }

                var typeDescriptor = instanceType.Descriptor();
                if (typeDescriptor.IsConstructedGenericType())
                {
                    buildContext.BindTypes(instanceType, buildContext.Key.Type);
                    var genericArgs = typeDescriptor.GetGenericTypeArguments();
                    var isReplaced  = false;
                    for (var position = 0; position < genericArgs.Length; position++)
                    {
                        if (buildContext.TryReplaceType(genericArgs[position], out var type))
                        {
                            genericArgs[position] = type;
                            isReplaced            = true;
                        }
                    }

                    if (isReplaced)
                    {
                        typeDescriptor = typeDescriptor.GetGenericTypeDefinition().MakeGenericType(genericArgs).Descriptor();
                    }
                }

                var defaultConstructors = CreateMethods(buildContext.Container, typeDescriptor.GetDeclaredConstructors());
                if (!autoWiringStrategy.TryResolveConstructor(defaultConstructors, out var ctor))
                {
                    if (isDefaultAutoWiringStrategy || !DefaultAutowiringStrategy.Shared.TryResolveConstructor(defaultConstructors, out ctor))
                    {
                        ctor = buildContext.Container.Resolve <IIssueResolver>().CannotResolveConstructor(defaultConstructors);
                    }
                }

                var defaultMethods = CreateMethods(buildContext.Container, typeDescriptor.GetDeclaredMethods());
                if (!autoWiringStrategy.TryResolveInitializers(defaultMethods, out var initializers))
                {
                    if (isDefaultAutoWiringStrategy || !DefaultAutowiringStrategy.Shared.TryResolveInitializers(defaultMethods, out initializers))
                    {
                        initializers = Enumerable.Empty <IMethod <MethodInfo> >();
                    }
                }

                baseExpression = Expression.New(ctor.Info, ctor.GetParametersExpressions(buildContext));
                var curInitializers = initializers.ToArray();
                if (curInitializers.Length > 0)
                {
                    var thisVar = Expression.Variable(baseExpression.Type, "this");
                    baseExpression = Expression.Block(
                        new[] { thisVar },
                        Expression.Assign(thisVar, baseExpression),
                        Expression.Block(
                            from initializer in initializers
                            select Expression.Call(thisVar, initializer.Info, initializer.GetParametersExpressions(buildContext))
                            ),
                        thisVar
                        );
                }

                if (!isDefaultAutoWiringStrategy)
                {
                    baseExpression = buildContext.InjectDependencies(baseExpression);
                }

                baseExpression = buildContext.AddLifetime(baseExpression, lifetime);
                error          = default(Exception);
                return(true);
            }
            catch (BuildExpressionException ex)
            {
                error          = ex;
                baseExpression = default(Expression);
                return(false);
            }
        }