Comment utiliser L'Injection de propriété avec AutoFac?
dans une application Console, J'utilise Log4Net et dans la méthode principale j'obtiens l'objet logger. Maintenant, j'aimerais rendre cet objet log disponible dans toutes mes classes en laissant toutes les classes hériter d'une classe de BaseClass qui a une propriété ILog et qui est supposée être réglée par injection de propriété plutôt que par Injection de constructeur.
J'utilise Autofac conteneur CIO, comment injecter mon objet log à la propriété Log de ma chaque classe?
Quelle est la meilleure façon/la plus facile pour y parvenir?
Est-il possible de résoudre automatiquement les types?
ci-dessous est mon application test:
namespace ConsoleApplication1
{
class Program
{
static ILog Log;
static IContainer Container;
static void Main(string[] args)
{
InitializeLogger();
InitializeAutoFac();
// the below works but could it be done automatically (without specifying the name of each class)?
Product.Log = Container.Resolve<ILog>();
// tried below but didn't inject ILog object into the Product
Container.Resolve<Product>();
RunTest();
Console.ReadLine();
}
private static void RunTest()
{
var product = new Product();
product.Do();
}
private static void InitializeAutoFac()
{
var builder = new ContainerBuilder();
builder.Register(c => Log).As<ILog>();
builder.RegisterType<Product>().PropertiesAutowired();
Container = builder.Build();
}
private static void InitializeLogger()
{
log4net.Config.XmlConfigurator.Configure();
Log = LogManager.GetLogger("LoggerName");
}
}
public class Product
{
public static ILog Log { get; set; }
public void Do()
{
// this throws exception because Log is not set
Log.Debug("some Debug");
}
}
}
4 réponses
À mon avis la solution Ninject créer est beaucoup plus agréable que la propertyinjection dans Autofac. Par conséquent, j'ai créé un attribut personnalisé qui est un aspect postsharp qui injecte automatiquement mes classes:
[AutofacResolve]
public IStorageManager StorageManager { get; set; }
mon aspect:
[Serializable]
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class AutofacResolveAttribute : LocationInterceptionAspect
{
public override void OnGetValue(LocationInterceptionArgs args)
{
args.ProceedGetValue();
if (!args.Location.LocationType.IsInterface) return;
if ( args.Value != null )
{
args.Value = DependencyResolver.Current.GetService(args.Location.LocationType);
args.ProceedSetValue();
}
}
}
je sais que la réponse à la question est déjà donnée mais j'ai pensé que c'était une façon très soignée de résoudre l'injection de propriété automatique dans Autofac. Ce sera peut-être utile à quelqu'un dans le avenir.
Utiliser Injection De La Propriété:
builder.Register(c => LogManager.GetLogger("LoggerName"))
.As<ILog>();
builder.RegisterType<CustomClass>()
.PropertiesAutowired();
L'injection immobilière fonctionne pour Propriétés et pas Champs. Dans votre classe, Log est un champ et non une propriété et par conséquent il ne sera jamais résolu par L'Autofac.
Je ne voulais pas utiliser postsharp donc j'ai fait une solution rapide, mais il ne s'auto-injecte pas. Je suis nouveau à Autofac, et il devrait être possible de s'appuyer sur cette solution.
[Serializable]
[AttributeUsage(AttributeTargets.Property)]
public class AutofacResolveAttribute : Attribute
{
}
public class AutofactResolver
{
/// <summary>
/// Injecting objects into properties marked with "AutofacResolve"
/// </summary>
/// <param name="obj">Source object</param>
public static void InjectProperties(object obj)
{
var propertiesToInject = obj.GetType().GetProperties()
.Where(x => x.CustomAttributes.Any(y => y.AttributeType.Name == nameof(AutofacResolveAttribute))).ToList();
foreach (var property in propertiesToInject)
{
var objectToInject = Autofact.SharedContainer.Resolve(property.PropertyType);
property.SetValue(obj, objectToInject, null);
}
}
}
l'Utiliser avec cet appel:
AutofactResolver.InjectProperties(sourceObject);