コード例 #1
0
        /// <summary>
        /// Builds an expression which represents an instance of <see cref="IEnumerable{T}"/> whose elements are created by the
        /// <see cref="EnumerableTarget.Targets"/> of the passed <paramref name="target"/>.
        /// </summary>
        /// <param name="target">The target for which an expression is to be built.</param>
        /// <param name="context">The current compilation context.</param>
        /// <param name="compiler">The compiler to use when building expressions for child targets.</param>
        /// <returns>An expression which can be compiled into a delegate that, when executed, will create an instance of the enumerable
        /// represented by <paramref name="target"/>
        /// </returns>
        /// <remarks>
        /// The compiler is capable of producing both lazy-loaded and eager-loaded enumerables, which can be controlled via
        /// target container options.
        ///
        /// ## Lazy vs Eager loading
        ///
        /// The option <see cref="Options.LazyEnumerables"/> is read from the <paramref name="context"/> for the
        /// <see cref="EnumerableTarget.ElementType"/> of the <paramref name="target"/>.  If it is equivalent to <c>true</c>
        /// (the <see cref="Options.LazyEnumerables.Default"/>), then a lazily-loaded enumerable is constructed which will
        /// create new instances of each object in the enumerable each time it is enumerated.
        ///
        /// If the option is instead equivalent to <c>false</c>, then all instances will be created in advance, and an already-materialised
        /// enumerable is constructed.</remarks>
        protected override Expression Build(EnumerableTarget target, IExpressionCompileContext context, IExpressionCompiler compiler)
        {
            if (context.GetOption(target.ElementType, Options.LazyEnumerables.Default))
            {
                var funcs =
                    target.Targets.Select(t => compiler.BuildResolveLambdaStrong(t, context.NewContext(target.ElementType)).Compile())
                    .ToArray();

                var lazyType = typeof(LazyEnumerable <>).MakeGenericType(target.ElementType);

                var ctor = lazyType.GetConstructor(new[] { typeof(Delegate[]) });

                var lazy = ctor.Invoke(new object[] { funcs });

                return(Expression.Call(
                           Expression.Constant(lazy),
                           "GetInstances",
                           null,
                           context.ResolveContextParameterExpression));
            }
            else
            {
                List <Expression> all = new List <Expression>();

                for (var f = 0; f < target.Targets.Length; f++)
                {
                    all.Add(compiler.Build(target.Targets[f], context.NewContext(target.ElementType)));
                }

                return(Expression.New(
                           typeof(EagerEnumerable <>).MakeGenericType(target.ElementType).GetConstructors()[0],
                           Expression.NewArrayInit(target.ElementType, all)));
            }
        }
コード例 #2
0
        /// <summary>
        /// Builds an expression for the given <paramref name="target"/>.
        /// </summary>
        /// <param name="target">The target whose expression is to be built.</param>
        /// <param name="context">The compilation context.</param>
        /// <param name="compiler">The expression compiler to be used to build any other expressions for targets
        /// which might be required by the <paramref name="target" />.  Note that unlike on the interface, where this
        /// parameter is optional, this will always be provided</param>
        protected override Expression Build(SingletonTarget target, IExpressionCompileContext context, IExpressionCompiler compiler)
        {
            var             holder           = context.ResolveContext.Resolve <SingletonTarget.SingletonContainer>();
            int?            targetIdOverride = context.GetOption <TargetIdentityOverride>(context.TargetType ?? target.DeclaredType);
            TypeAndTargetId id = new TypeAndTargetId(context.TargetType ?? target.DeclaredType, targetIdOverride ?? target.Id);

            var lazy = holder.GetLazy(id);

            if (lazy == null)
            {
                lazy = holder.GetLazy(
                    target,
                    id,
                    compiler.CompileTargetStrong(
                        target.InnerTarget,
                        context.NewContext(
                            context.TargetType ?? target.DeclaredType,
                            // this override is important - when forcing into the root-scope, as we do
                            // for singletons, 'explicit' means absolutely nothing.  So, instead of allowing
                            // our child target to choose, we explicitly ensure that all instances are implicitly
                            // tracked within the root scope, if it is one which can track instances.
                            scopeBehaviourOverride: ScopeBehaviour.Implicit,
                            scopePreferenceOverride: ScopePreference.Root)),
                    context);
            }

            return(Expression.Call(
                       Expression.Constant(lazy),
                       lazy.GetType().GetMethod("Resolve"),
                       context.ResolveContextParameterExpression));
        }
コード例 #3
0
        private static void TrackCompilation(ITarget target, IExpressionCompileContext context)
        {
            Type theType          = context.TargetType ?? target.DeclaredType;
            int? targetIdOverride = context.GetOption <Runtime.TargetIdentityOverride>(theType);

            _compiledTargets.GetOrAdd(targetIdOverride ?? target.Id, target);
            _compileCounts.AddOrUpdate(new TypeAndTargetId(theType, targetIdOverride ?? target.Id), 1, (k, i) => i + 1);
        }
コード例 #4
0
        /// <summary>
        /// Resolves an expression builder that can build the given target for the given compile context.
        ///
        /// Or
        ///
        /// Returns null if no builder can be found.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="context">The context.</param>
        /// <remarks>The function builds a list of all the types in the hierarchy represented
        /// by the type of the <paramref name="target"/> and, for each of those types which are
        /// compatible with <see cref="ITarget"/>, it looks for an <see cref="IExpressionBuilder{TTarget}"/>
        /// which is specialised for that type.  If no compatible builder is found, then it attempts
        /// to find a general purpose <see cref="IExpressionBuilder"/> which can build the type.</remarks>
        public virtual IExpressionBuilder ResolveBuilder(ITarget target, IExpressionCompileContext context)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            return(context.GetOption <IExpressionBuilder>(target.GetType()));
        }