Could we make it optional to provide a ILoggerFactory and resolve it?
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?
I would rather have it as Lazy<ILoggerFactory> but otherwise I like your idea.
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.
Resolving ILoggerFactroy is slow
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
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.