Есть пример чего-то подобного в документах Autofac , который использует log4net.Вместо Logger.For<T>()
это LogManager.GetLogger(typeof(T))
, но оно имеет место.
Первым шагом будет выяснить для данного объекта Type
, как создать универсальный вызов метода.Вы можете сделать это с помощью MethodInfo.MakeGenericMethod
.
Что-то вроде ...
private static object GetLogger(Type forType)
{
// Get the LogManager.For<T>() method.
var openMethod = typeof(LogManager).GetMethod("For", BindingFlags.Public | BindingFlags.Static);
// Actually put the T in For<T>().
var closedMethod = openMethod.MakeGenericMethod(forType);
// Invoke the static method.
return closedMethod.Invoke(null, null);
}
Теперь вы можете использовать пример практически из коробки.
public class LoggingModule : Autofac.Module
{
private static void InjectLoggerProperties(object instance)
{
var instanceType = instance.GetType();
// Get all the injectable properties to set.
// If you wanted to ensure the properties were only UNSET properties,
// here's where you'd do it. Also, update the typeof() call/filter thing
// here as needed.
var properties = instanceType
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType == typeof(ILog) && p.CanWrite && p.GetIndexParameters().Length == 0);
// Set the properties located.
foreach (var propToSet in properties)
{
propToSet.SetValue(instance, LogManager.GetLogger(instanceType), null);
}
}
private static void OnComponentPreparing(object sender, PreparingEventArgs e)
{
e.Parameters = e.Parameters.Union(
new[]
{
// Again, update the check here to ensure you're only filling in the
// right parameters.
new ResolvedParameter(
(p, i) => p.ParameterType == typeof(ILog),
// Here's the call to that generic method.
(p, i) => GetLogger(p.Member.DeclaringType)
),
});
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
// Handle constructor parameters.
registration.Preparing += OnComponentPreparing;
// Handle properties.
registration.Activated += (sender, e) => InjectLoggerProperties(e.Instance);
}
private static object GetLogger(Type forType)
{
// Get the LogManager.For<T>() method.
var openMethod = typeof(LogManager).GetMethod("For", BindingFlags.Public | BindingFlags.Static);
// Actually put the T in For<T>().
var closedMethod = openMethod.MakeGenericMethod(forType);
// Invoke the static method.
return closedMethod.Invoke(null, null);
}
}
Предостережение: Я на самом деле не скомпилировал это.Я довольно быстро схожу с макушки головы.Но это должно сделать это.