Skip to content

Could we make it optional to provide a ILoggerFactory and resolve it? #3

@pksorensen

Description

@pksorensen

My usecase is that the ILoggerFactory is build as part of startup and I want to lazy create it until the first ILogger is needed.

I modified the extension

public class LoggingExtension : UnityContainerExtension,
                                   IBuildPlanCreatorPolicy,
                                   IBuildPlanPolicy
    {
        #region Fields

        private readonly MethodInfo _createLoggerMethod = typeof(LoggingExtension).GetTypeInfo()
                                                                                  .GetDeclaredMethod(nameof(CreateLogger));

        #endregion


        #region Constructors

        //[InjectionConstructor]
        //public LoggingExtension()
        //{
        //    LoggerFactory = new LoggerFactory();
        //}

        //public LoggingExtension(ILoggerFactory factory)
        //{
        //    LoggerFactory = factory ?? new LoggerFactory();
        //}


        #endregion


        #region Public Members

        //public ILoggerFactory LoggerFactory { get; }

        #endregion


        #region IBuildPlanPolicy


        public void BuildUp(IBuilderContext context)
        {    
            context.Existing = null == context.ParentContext
                             ? context.ParentContext.Container.Resolve<ILoggerFactory>().CreateLogger(context.OriginalBuildKey.Name ?? string.Empty)
                             : context.Container.Resolve<ILoggerFactory>().CreateLogger(context.ParentContext.BuildKey.Type);
            context.BuildComplete = true;
        }

        #endregion


        #region IBuildPlanCreatorPolicy

        IBuildPlanPolicy IBuildPlanCreatorPolicy.CreatePlan(IBuilderContext context, INamedType buildKey)
        {
            var info = (context ?? throw new ArgumentNullException(nameof(context))).BuildKey
                                                                                    .Type
                                                                                    .GetTypeInfo();
            if (!info.IsGenericType) return this;

            var buildMethod = _createLoggerMethod.MakeGenericMethod(info.GenericTypeArguments.First())
                                                 .CreateDelegate(typeof(DynamicBuildPlanMethod));

            return new DynamicMethodBuildPlan((DynamicBuildPlanMethod)buildMethod, context.Container.Resolve<ILoggerFactory>());
        }

        #endregion


        #region Implementation

        private static void CreateLogger<T>(IBuilderContext context, ILoggerFactory loggerFactory)
        {
            context.Existing = loggerFactory.CreateLogger<T>();
            context.BuildComplete = true;
        }

        protected override void Initialize()
        {
            Context.Policies.Set(typeof(ILogger), string.Empty, typeof(IBuildPlanPolicy), this);
            Context.Policies.Set<IBuildPlanCreatorPolicy>(this, typeof(ILogger));
            Context.Policies.Set<IBuildPlanCreatorPolicy>(this, typeof(ILogger<>));
        }

        private delegate void DynamicBuildPlanMethod(IBuilderContext context, ILoggerFactory loggerFactory);

        private class DynamicMethodBuildPlan : IBuildPlanPolicy
        {
            private readonly DynamicBuildPlanMethod _buildMethod;
            private readonly ILoggerFactory _loggerFactory;

            /// <summary>
            /// 
            /// </summary>
            /// <param name="buildMethod"></param>
            /// <param name="loggerFactory"></param>
            public DynamicMethodBuildPlan(DynamicBuildPlanMethod buildMethod,
                                          ILoggerFactory loggerFactory)
            {
                _buildMethod = buildMethod;
                _loggerFactory = loggerFactory;
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="context"></param>
            public void BuildUp(IBuilderContext context)
            {
                _buildMethod(context, _loggerFactory);
            }
        }

        #endregion
    }

What do you think, should we consider resolving it instead of giving it when constructing the extension?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions