Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
pksorensen opened this issue Sep 16, 2018 · 5 comments
Open

Comments

@pksorensen
Copy link

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?

@ENikS
Copy link
Contributor

ENikS commented Sep 16, 2018

I would rather have it as Lazy<ILoggerFactory> but otherwise I like your idea.

@pksorensen
Copy link
Author

how would that work? My case is that the container already have a registration for ILoggerFactory.

Should i then add one extra registration for Lazy<ILoggerFactory> => InjectionFactory((c)=> new Lazy(c.resolve<ILoggerFactory>()).

Feels like i am missing something.

@ENikS
Copy link
Contributor

ENikS commented Sep 16, 2018

Resolving ILoggerFactroy is slow

@ENikS
Copy link
Contributor

ENikS commented Sep 16, 2018

It could be something like this:

[InjectionConstructor]
public LoggingExtension()
{
    _loggerFactory = new Lazy<ILoggerFactory>(() => new LoggerFactory());
}
...

Also, user should be able to provide his own instance of ILoggerFactory

@pksorensen
Copy link
Author

public class MyLoggerFactory : ILoggerFactory
{
    public MyLoggerFactory(IEnumerable<ILoggerFactoryPlugin> plugins){

    }

}


var container = new UnityContainer();


container.RegisterType<ILoggerFactory,MyLoggerFactory>();

container.AddNewExtension<LoggingExtension>();

container.RegisterType<ILoggerFactoryPlugin,MyPlugin>();

var logger = container.resolve<ILogger<Test>>();

I dont understand how your example will work with the given example here. The container knows about ILoggerFactory and it cannot be created at the time of adding the logging extension.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants