Skip to content

Instantly share code, notes, and snippets.

@sheastrickland
Last active August 29, 2015 14:23
Show Gist options
  • Save sheastrickland/e2899cd7abe61e20de69 to your computer and use it in GitHub Desktop.
Save sheastrickland/e2899cd7abe61e20de69 to your computer and use it in GitHub Desktop.
[Fact]
void Main()
{
var cb = new ContainerBuilder();
cb.RegisterModule(new LoggingModule<log4net.ILog>(log4net.LogManager.GetLogger));
cb.RegisterModule(new LoggingModule<Serilog.ILogger>(Serilog.Log.ForContext));
cb.RegisterType<HasLogProperty>();
cb.RegisterType<HasLogCtor>();
var container = cb.Build();
//ctor, when parent is resolved by container
var ctorinstance = container.Resolve<HasLogCtor>();
Assert.NotNull(ctorinstance.Logger);
Assert.NotNull(ctorinstance.Log);
Assert.Equal(typeof(HasLogCtor).FullName, ctorinstance.Log.Logger.Name);
//properties, when parent is resolved by container
var propinstance = container.Resolve<HasLogProperty>();
Assert.NotNull(propinstance.Logger);
Assert.NotNull(propinstance.Log);
Assert.Equal(typeof(HasLogProperty).FullName, propinstance.Log.Logger.Name);
//properties of existing instance (think WebForms Page / UserControl instance)
var existinginstance = new InstanceLogProperty();
container.InjectProperties(existinginstance);
Assert.NotNull(existinginstance.Logger);
Assert.NotNull(existinginstance.Log);
Assert.Equal(typeof(InstanceLogProperty).FullName, existinginstance.Log.Logger.Name);
}
public class InstanceLogProperty
{
public log4net.ILog Log { get; set; }
public Serilog.ILogger Logger { get; set; }
}
public class HasLogProperty
{
public log4net.ILog Log { get; set; }
public Serilog.ILogger Logger { get; set; }
}
public class HasLogCtor
{
public HasLogCtor(log4net.ILog log, Serilog.ILogger logger)
{
Log = log;
Logger = logger;
}
public log4net.ILog Log { get; private set; }
public Serilog.ILogger Logger { get; private set; }
}
public class LoggingModule<TLogger> : Autofac.Module
{
private readonly Func<Type, TLogger> _logFactory;
public LoggingModule(Func<Type,TLogger> logFactory)
{
_logFactory = logFactory;
}
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
//NOTE: this is needed due to context.IsRegistered(propertyType) check in AutowiringPropertyInjector.InjectProperties, followed by context.Resolve(propertyType)
builder.Register((context, parameters) => _logFactory(parameters.Named<Type>(ResolutionExtensions.PropertyInjectedInstanceTypeNamedParameter)));
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
var type = registration.Activator.LimitType;
if (HasPropertyDependencyOnLogger(type))
{
registration.Activated += InjectLoggerViaProperty;
}
if (HasConstructorDependencyOnLogger(type))
{
registration.Preparing += InjectLoggerViaConstructor;
}
}
private bool HasPropertyDependencyOnLogger(Type type)
{
return type.GetProperties().Any(property => property.CanWrite && property.PropertyType == typeof (TLogger));
}
private bool HasConstructorDependencyOnLogger(Type type)
{
return type.GetConstructors()
.SelectMany(constructor => constructor.GetParameters()
.Where(parameter => parameter.ParameterType == typeof (TLogger)))
.Any();
}
private void InjectLoggerViaProperty(object sender, ActivatedEventArgs<object> @event)
{
@event.Context.InjectProperties(@event.Instance);
}
private void InjectLoggerViaConstructor(object sender, PreparingEventArgs @event)
{
var type = @event.Component.Target.Activator.LimitType;
@event.Parameters = @event.Parameters.Union(new[]
{
new ResolvedParameter((parameter, context) => parameter.ParameterType == typeof (TLogger), (p, i) => _logFactory(type))
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment