/// <inheritdoc/>
        public override IGenerationContext Customize(ConstructionContextDefinition constructionContextDefinition)
        {
            if (constructionContextDefinition == null)
            {
                throw new ArgumentNullException(nameof(constructionContextDefinition));
            }

            var wrapper = new GenerationContextWrapper(Inner, constructionContextDefinition);

            return(wrapper);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="GenerationContextWrapper"/> class.
 /// </summary>
 /// <param name="registrations">The setup <see cref="GenerationContext.Registrations"/>.</param>
 /// <param name="compositions">The <see cref="GenerationContext.Compositions"/> for code generation.</param>
 /// <param name="usingSimpleNames">
 /// A value indicating whether simple names should be generated for compose methods.
 /// </param>
 /// <param name="extraDataType">The type of the <see cref="ConstructionContext{T}.Extra"/> data.</param>
 /// <param name="constructionContext">The type of the <see cref="ConstructionContext{T}"/>.</param>
 public GenerationContextWrapper(
     IReadOnlyDictionary <Type, IReadOnlyList <IRegistration> > registrations,
     IReadOnlyDictionary <Type, IComposition> compositions,
     bool usingSimpleNames,
     string extraDataType       = null,
     string constructionContext = null)
     : base(registrations, compositions, usingSimpleNames, extraDataType, constructionContext)
 {
     ConstructionContextDefinition =
         new ConstructionContextDefinition(typeof(void), typeof(void), typeof(void));
     Inner = this;
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="GenerationContextWrapper"/> class.
        /// </summary>
        /// <param name="inner">The inner <see cref="GenerationContext"/> wrapped by this instance.</param>
        /// <param name="constructionContextDefinition">The <see cref="ConstructionContextDefinition"/>.</param>
        private GenerationContextWrapper(
            GenerationContext inner,
            ConstructionContextDefinition constructionContextDefinition)
            : base(inner.Registrations, inner.Compositions, inner.UsingSimpleNames, inner.ExtraDataType, inner.ConstructionContext)
        {
            if (constructionContextDefinition == null)
            {
                throw new ArgumentNullException(nameof(constructionContextDefinition));
            }

            Inner = inner;
            ConstructionContextDefinition = constructionContextDefinition;
        }
        /// <summary>
        /// Creates a customized <see cref="IGenerationContext"/> where the
        /// <see cref="IGenerationContext.ConstructionContextDefinition"/> is updated with the specified parameters.
        /// </summary>
        /// <param name="context">The <see cref="IGenerationContext"/> to customize.</param>
        /// <param name="implementationType">
        /// The <see cref="ConstructionContextDefinition.ImplementationType"/>.
        /// </param>
        /// <param name="serviceType">The <see cref="ConstructionContextDefinition.ServiceType"/>.</param>
        /// <param name="recipientType">The <see cref="ConstructionContextDefinition.RecipientType"/>.</param>
        /// <returns>
        /// A customized <see cref="IGenerationContext"/> where the
        /// <see cref="IGenerationContext.ConstructionContextDefinition"/> is updated with the specified parameters.
        /// </returns>
        public static IGenerationContext Customize(
            this IGenerationContext context,
            Type implementationType = null,
            Type serviceType        = null,
            Type recipientType      = null)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            implementationType = implementationType ?? context.ConstructionContextDefinition.ImplementationType;
            serviceType        = serviceType ?? context.ConstructionContextDefinition.ServiceType;
            recipientType      = recipientType ?? context.ConstructionContextDefinition.RecipientType;

            var definition = new ConstructionContextDefinition(implementationType, serviceType, recipientType);
            IGenerationContext customization = context.Customize(definition);

            return(customization);
        }
Example #5
0
        private static string GenerateGetServiceMethod(GenerationContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            string parameter = context.HasConstructionContext
                ? $",{NewLine}    {context.ExtraDataType} extraData"
                : string.Empty;

            string contextVariable = context.HasConstructionContext
                ? $"{NewLine}    var context = {context.ConstructionContext}.Default.Initialize(this, extraData);"
                : string.Empty;

            var builder = new StringBuilder(1024);

            builder.AppendFormat(
                "public object GetService({0}    System.Type serviceType{1}){0}{{{2}{0}    " +
                "switch (serviceType.GetHashCode()){0}    {{",
                NewLine,
                parameter,
                contextVariable);

            // Get the single mappings, i.e. where only one service is returned for a type.
            IEnumerable <(Type key, IComposition composition)> singleIocMappings =
                from kvp in context.Registrations
                let regTypes = kvp.Value.DistinctPublicRegistrationTypes().ToList()
                               where regTypes.Count == 1
                               orderby kvp.Key.GetHashCode()
                               select(kvp.Key, context.Compositions[regTypes[0]]);

            IEnumerable <string> caseSnippets = singleIocMappings.Select(m => GetCaseSnippet(m.key, m.composition));
            string caseStatements             = string.Join(NewLine, caseSnippets);

            caseStatements = CodeGen.Indent(NewLine + caseStatements, 2);
            builder.Append(caseStatements);

            string GetCaseSnippet(Type key, IComposition composition)
            {
                var    definition         = new ConstructionContextDefinition(composition.Type, key, typeof(void));
                string keyComment         = key.ToCompileName();
                string instanceExpression = composition.GetInstanceExpression(context.Customize(definition));

                instanceExpression = CodeGen.Indent(instanceExpression);

                string caseSnippet =
                    $"case {key.GetHashCode()}: // {keyComment}{NewLine}    return {instanceExpression};";

                return(caseSnippet);
            }

            builder.AppendFormat("{0}    }}{0}{0}    return null;{0}}}", NewLine);

            // Add the genetic GetService method.
            if (context.HasConstructionContext)
            {
                builder.AppendFormat(
                    "{0}{0}public TService GetService<TService>({0}    {1} extraData){0}{{{0}    " +
                    "return (TService)GetService(typeof(TService), extraData);{0}}}",
                    NewLine,
                    context.ExtraDataType);
            }
            else
            {
                builder.AppendFormat(
                    "{0}{0}public TService GetService<TService>(){0}{{{0}    " +
                    "return (TService)GetService(typeof(TService));{0}}}",
                    NewLine);
            }

            return(builder.ToString());
        }