예제 #1
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));
        }