예제 #1
0
        public IInstanceFactory Handle(IResolverRequest request, Func<IResolverRequest, IInstanceFactory> nextHandler)
        {
            // pass if this is not a request for a Func<...>

            if (!request.RequestType.IsGenericType
                || request.RequestType.GetGenericTypeDefinition() != typeof(Func<>))

                return nextHandler(request);

            var innerType = request.RequestType.GetGenericArguments()[0];

            var factory = _pipeline.Resolve(
                new ResolverRequest(
                    innerType,
                    request.Context,
                    request.Args)
                );

            if (factory == null) return null;

            var funcType = typeof(Func<>).MakeGenericType(innerType);

            return new InstanceFactory(
                request.RequestType,
                Expression.Lambda( // Factory of...
                    Expression.Lambda( // Factory of...
                        Expression.Convert(factory.BuildExpression.Body, innerType)) //... (T)value
                    ));
        }
예제 #2
0
        public IInstanceFactory Handle(IResolverRequest request, Func<IResolverRequest, IInstanceFactory> nextHandler)
        {
            if (request == null) throw new ArgumentNullException("request");
            if (nextHandler == null) throw new ArgumentNullException("nextHandler");

            // If the component handler is last in the pipeline, this will return null.
            // However, it might not *always* be the last handler, so stick to the pattern
            // and pass to the next handler rather than returning null explicitly.
            if (request.RequestType.IsAbstract) return nextHandler(request);

            var ctors = request.RequestType
                .GetConstructors(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);

            // this bad boy does the actual resolving...
            var ctorResolver = new ConstructorResolver(_pipeline);

            // ... we just order the results
            var factory = ctors
                .Select(ctor => ctorResolver.TryResolve(request, ctor))
                .Where(f => f != null) // remove unresolvable ctors
                .OrderByDescending(f => f.Resolvable) // order by most parameters
                .OrderBy(f => f.Optional) // with the least optional parameters
                .FirstOrDefault();

            return factory;
        }
예제 #3
0
        public IInstanceFactory Handle(IResolverRequest request,
                                       Func<IResolverRequest, IInstanceFactory> nextBehaviour)
        {
            // If this is not a parameter request then pass
            var paramRequest = request as ParameterRequest;
            if (paramRequest == null)
                return nextBehaviour(request);

            // if Resolver Args are present and there's an arg that satisfies this parameter
            if (paramRequest.Args != null
                && paramRequest.Args.HasValueFor(paramRequest.Parameter.ParameterType, paramRequest.Parameter.Name))
            {
                var value = request.Args.GetValueFor(paramRequest.Parameter.Name);
                return new InstanceFactory(
                    request.RequestType,
                    Expression.Lambda(Expression.Constant(value)));
            }

            // We couldn't resolve from ResolverArgs, so let the resolver pipeline run.
            // If there's a result, return it.

            var result = nextBehaviour(request);
            if (result != null) return result;

            // If not, our final option is to use the parameter default value if it has one
            return (paramRequest.Parameter.IsOptional)
                       ? new InstanceFactory(
                             request.RequestType,
                             Expression.Lambda(Expression.Constant(paramRequest.Parameter.DefaultValue)))
                       : null;
        }
예제 #4
0
        public IInstanceFactory Handle(IResolverRequest request, Func<IResolverRequest,IInstanceFactory> nextHandler)
        {
            // this test handler handles requests for ITestComponent.
            // additionally, it only handles when there is a "Key" arg matching the _key value.
            if (request.RequestType != typeof(ITestComponent)
                || request.Args == null
                || !request.Args.HasValueFor(typeof(string),"Key")
                || (string)request.Args.GetValueFor("Key") != _key)
                return nextHandler(request);

            return new InstanceFactory(typeof(ITestComponent), ()=> _testable);
        }
예제 #5
0
        public ConstructorFactory TryResolve(IResolverRequest request, ConstructorInfo ctor)
        {
            if (request == null) throw new ArgumentNullException("request");

            var parameters = ctor.GetParameters();

            // if this is the default ctor, then return a factory that calls the default ctor
            if (parameters.Length == 0)
                return new ConstructorFactory(
                    request.RequestType,
                    Expression.Lambda(Expression.New(ctor)), 0, 0);

            // for each parameter in the ctor, ask the resolver pipeline for a suitable factory.
            // Break if any parameters are unresolvable
            var factories = parameters
                .Select(p =>
                        _pipeline
                            .Resolve(new ParameterRequest(p, request.Context, request.Args)))
                .TakeWhile(factory => factory != null)
                .ToArray();

            // if the factory count doesn't match the parameter count,
            // then this ctor is unresolvable, so return null.
            if(factories.Length != parameters.Length)
                return null;

            // Count how many ctor parameters are optional because we can use this to settle a tie
            // between constructors. Where ctors with the same number of resolvable parameters are
            // available, then attempt to choose the ctor with the fewest optional parameters.
            var optional = parameters.Count(p => p.IsOptional);

            // Package up the parameter factories as a constructor factory
            return new ConstructorFactory(
                request.RequestType,
                Expression.Lambda(
                    Expression.New(
                        ctor,
                        factories.Select(f => f.BuildExpression.Body))),
                parameters.Length,
                optional
                );
        }
예제 #6
0
        public IInstanceFactory Handle(IResolverRequest request, Func<IResolverRequest, IInstanceFactory> nextHandler)
        {
            if (request == null) throw new ArgumentNullException("request");
            if (nextHandler == null) throw new ArgumentNullException("nextHandler");

            // pass if this is not a request for a Lazy<...>
            if (!request.RequestType.IsGenericType
                || request.RequestType.GetGenericTypeDefinition() != typeof (Lazy<>))
                return nextHandler(request);

            // attemp to get a factory for the T in Lazy<T>
            var innerType = request.RequestType.GetGenericArguments()[0];
            var inner = _pipeline.Resolve(new ResolverRequest(innerType, request.Context, request.Args));
            if (inner == null) return null;

            // find the ctor for Lazy<T> that takes a Func<T>
            var funcType = typeof (Func<>).MakeGenericType(innerType);
            var lazyType = typeof (Lazy<>).MakeGenericType(innerType);
            var ctor = lazyType.GetConstructor(new[] {funcType});

            return new InstanceFactory(
                request.RequestType,
                MakeLazyExpression(inner.BuildExpression, innerType, ctor));
        }
예제 #7
0
 internal IInstanceFactory Handle(IResolverRequest request)
 {
     return _index == _handlers.Count
                ? null
                : _handlers[_index++].Handle(request, Handle);
 }
예제 #8
0
 public IInstanceFactory Resolve(IResolverRequest request)
 {
     return new Iterator(_handlers).Handle(request);
 }